diff -urN cahier-de-prepa8.0.2/ajax.php cahier-de-prepa8.1.0/ajax.php
--- cahier-de-prepa8.0.2/ajax.php	2018-10-22 00:27:14.846078696 +0200
+++ cahier-de-prepa8.1.0/ajax.php	2018-10-30 10:34:46.535499386 +0100
@@ -93,6 +93,8 @@
 //////////////////////////////
 elseif ( ( $action == 'prefsperso' ) && ( $autorisation > 1 ) )  {
 
+  // Spécifications pour les manipulations de caractères sur 2 octets (accents)
+  mb_internal_encoding('UTF-8');
   // Vérification obligatoire du mot de passe
   if ( !isset($_REQUEST['mdp']) )
     exit('{"etat":"nok","message":"Mot de passe incorrect"}');
@@ -223,9 +225,12 @@
   // Connexion normale obligatoire
   connexionlight();
   $mysqli = connectsql(true);
+  // Spécifications pour les manipulations de caractères sur 2 octets (accents)
+  mb_internal_encoding('UTF-8');
 
   // Vérification que l'identifiant est valide
-  $resultat = $mysqli->query("SELECT matiere, DATE_FORMAT(jour,'%w%Y%m%e') AS date, DATE_FORMAT(jour,'%Y-%m-%d') AS jour, TIME_FORMAT(heure,'%k:%i') AS heure, duree, releve>0 AS releve 
+  $resultat = $mysqli->query("SELECT matiere, DATE_FORMAT(jour,'%w%Y%m%e') AS date, DATE_FORMAT(jour,'%Y-%m-%d') AS jour,
+                              TIME_FORMAT(heure,'%k:%i') AS heure, duree, releve>0 AS releve, description 
                               FROM heurescolles WHERE id = $id AND colleur = ${_SESSION['id']}");
   if ( !$resultat->num_rows )
     exit('{"etat":"nok","message":"Identifiant non valide"}');
@@ -234,7 +239,15 @@
   $matiere = $r['matiere'];
   
   // Suppression
-  if ( isset($_REQUEST['supprime']) && ( $r['releve'] == 0 ) )  {
+  if ( isset($_REQUEST['supprime']) )  {
+    if ( $r['releve'] > 0 )
+      exit('{"etat":"nok","message":"La colle n\'a pas été supprimée car elle a déjà été relevée."}');
+    // Heures en séances de TD (pas de notes associées)
+    if ( strlen($r['description']) )
+      exit( requete('heurescolles',"DELETE FROM heurescolles WHERE id = $id",$mysqli)
+          ? '{"etat":"ok","message":"La séance du <em>'.format_date($r['date']).'</em> a été supprimée."}'
+          : '{"etat":"nok","message":"La séance du <em>'.format_date($r['date']).'</em> n\'a pas été supprimée. Erreur MySQL n°'.$mysqli->errno.', «'.$mysqli->error.'»."}');
+    // Colle avec notes
     $resultat = $mysqli->query("SELECT * FROM notes WHERE heure = $id");
     $n = $resultat->num_rows;
     $resultat->free();
@@ -248,9 +261,41 @@
   // Modification
   if ( isset($_REQUEST['jour']) && isset($_REQUEST['heure']) )  {
     
+    // Heures en séances de TD (pas de notes associées)
+    if ( strlen($r['description']) )  {
+      $requete = array();
+      // Validation du jour
+      if ( $r['jour'] != ( $jour = preg_filter('/(\d{2})\/(\d{2})\/(\d{4})/','$3-$2-$1',$_REQUEST['jour']) ) )  {
+        // Vérification que le jour est bien dans l'année
+        $resultat = $mysqli->query("SELECT id FROM semaines WHERE debut <= '$jour' AND debut >= SUBDATE('$jour',7) ORDER BY debut DESC LIMIT 1");
+        if ( !$resultat->num_rows )
+          exit('{"etat":"nok","message":"Le jour choisi ne se trouve pas dans l\'année scolaire. S\'il s\'agit d\'une erreur, il faut peut-être contacter l\'administrateur."}');
+        $resultat->free();
+        $requete[] = "jour = '$jour'";
+      }
+      // Validation de l'heure
+      if ( ( $r['heure'] != ( $heure = preg_filter('/(\d{1,2})h(\d{2})/','$1:$2',$_REQUEST['heure']) ) ) && strlen($heure) )
+        $requete[] = "heure = '$heure'";
+      // Validation de la durée (séance non relevée uniquement)
+      if ( ( $r['releve'] == 0 ) && isset($_REQUEST['duree']) && ( $r['duree'] != ( $duree = call_user_func_array(function ($h,$m) { return intval($h)*60+intval($m); }, array_pad(explode('h',$_REQUEST['duree']),2,0)) ) && ( $duree > 0 ) ) )
+        $requete[] = "duree = '$duree'";
+      // Validation de la description
+      if ( ( $r['description'] != ( $description = trim(htmlspecialchars($_REQUEST['description'])) ) ) && strlen($description) )
+        $requete[] = 'description = \''.$mysqli->real_escape_string(mb_strtoupper(mb_substr($description,0,1)).mb_substr($description,1)).'\'';
+      // Écriture dans la table heurescolles
+      if ( $requete )  {
+        if ( requete('heurescolles','UPDATE heurescolles SET '.implode(', ',$requete)." WHERE id = $id",$mysqli) ) 
+          exit($_SESSION['message'] = '{"etat":"ok","message":"La séance du <em>'.format_date($r['date']).'</em> a été modifiée."}');
+        exit('{"etat":"nok","message":"La séance n\'a pas été modifiée. Erreur MySQL n°'.$mysqli->errno.', «'.$mysqli->error.'»."}');
+      }
+      else
+        exit('{"etat":"nok","message":"La séance du <em>'.format_date($r['date']).'</em> n\'a pas été modifiée. Aucune modification demandée."}');
+    }
+
     // Récupération des notes déjà existantes cette semaine
     $resultat = $mysqli->query("SELECT semaine, GROUP_CONCAT(eleve) AS dejanotes,
-                                GROUP_CONCAT(IF(heure=$id,eleve,NULL)) AS eleves, GROUP_CONCAT(IF(heure=$id,CONCAT(note,'-',id),NULL) SEPARATOR '|' ) AS notes
+                                GROUP_CONCAT(IF(heure=$id,eleve,NULL)) AS eleves,
+                                GROUP_CONCAT(IF(heure=$id,CONCAT(note,'-',id),NULL) SEPARATOR '|' ) AS notes
                                 FROM notes WHERE semaine = (SELECT semaine FROM notes WHERE heure = $id LIMIT 1) AND matiere = $matiere");
     $s = $resultat->fetch_assoc();
     $resultat->free();
@@ -258,7 +303,7 @@
     $notesperso = array_combine(explode(',',$s['eleves']),explode('|',$s['notes']));
     $dejanotes = $s['dejanotes'];
     $notes = array('0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','0,5','1,5','2,5','3,5','4,5','5,5','6,5','7,5','8,5','9,5','10,5','11,5','12,5','13,5','14,5','15,5','16,5','17,5','18,5','19,5','abs','nn');
-    $requete_heures = $requete_notes = $message = array();
+    $requete_generale = $requete_notes = $message = array();
     $etat = 'ok';
     
     // Validation du jour
@@ -267,12 +312,12 @@
       $resultat = $mysqli->query("SELECT DATEDIFF('$jour',debut) FROM semaines WHERE id = $semaine OR id = $semaine+1");
       $s = $resultat->fetch_row();
       if ( ( $s[0] >= 0 ) && ( ( $resultat->num_rows == 1 ) && ( $s[0] < 7 ) || ( $s = $resultat->fetch_row() ) && ( $s[0] < 0 ) ) )
-        $requete_heures[] = "jour = '$jour'";
+        $requete_generale[] = "jour = '$jour'";
       $resultat->free();
     }
     // Validation de l'heure
-    if ( $r['heure'] != ( $heure = preg_filter('/(\d{1,2})h(\d{2})/','$1:$2',$_REQUEST['heure']) ) && strlen($heure) )
-      $requete_heures[] = "heure = '$heure'";
+    if ( ( $r['heure'] != ( $heure = preg_filter('/(\d{1,2})h(\d{2})/','$1:$2',$_REQUEST['heure']) ) ) && strlen($heure) )
+      $requete_generale[] = "heure = '$heure'";
     
     // Si colle déjà relevée : modification des notes déjà mises uniquement
     if ( $r['releve'] == 1 )  {
@@ -284,8 +329,8 @@
     // modification/ajout/suppression de notes possible 
     else  {
       // Validation de la durée
-      if ( isset($_REQUEST['duree']) && ( $r['duree'] != ( $duree = call_user_func_array(function ($h,$m) { return intval($h)*60+intval($m); }, array_pad(explode('h',$_REQUEST['duree']),2,0)) )) )
-        $requete_heures[] = "duree = '$duree'";
+      if ( isset($_REQUEST['duree']) && ( $r['duree'] != ( $duree = call_user_func_array(function ($h,$m) { return intval($h)*60+intval($m); }, array_pad(explode('h',$_REQUEST['duree']),2,0))) ) && ( $duree > 0 ) )
+        $requete_generale[] = "duree = '$duree'";
       // Validation des notes déjà mises à modifier/supprimer
       foreach ( $notesperso as $eleve => $note )  {
         if ( !isset($_REQUEST["e$eleve"]) || !in_array($newnote = $_REQUEST["e$eleve"], $notes, true) )
@@ -306,8 +351,9 @@
     }
     
     // Exécution
-    if ( $requete_heures )  {
-      if ( requete('heurescolles','UPDATE heurescolles SET '.implode(', ',$requete_heures)." WHERE id = $id",$mysqli) ) 
+    if ( $requete_generale )  {
+      if ( requete('heurescolles','UPDATE heurescolles SET '.implode(', ',$requete_generale
+      )." WHERE id = $id",$mysqli) ) 
         $message[] = 'La colle du <em>'.format_date($r['date']).'</em> a été modifiée.';
       else  {
         $message[] = 'La colle du <em>'.format_date($r['date']).'</em> n\'a pas été modifiée. Erreur MySQL n°'.$mysqli->errno.', «'.$mysqli->error.'».';
@@ -341,16 +387,42 @@
 //////////////////////////////////////////////////////////////
 // Ajout de notes de colles (accès colleurs et professeurs) //
 //////////////////////////////////////////////////////////////
-elseif ( ( $action == 'ajout-notes' ) && ( ( $autorisation == 3 ) || ( $autorisation == 5 ) ) && isset($_REQUEST['sid']) && ctype_digit($sid = $_REQUEST['sid']) && isset($_REQUEST['matiere']) && in_array($matiere = intval($_REQUEST['matiere']),explode(',',$_SESSION['matieres'])) && isset($_REQUEST['jour']) && strlen($jour = preg_filter('/(\d{2})\/(\d{2})\/(\d{4})/','$3-$2-$1',$_REQUEST['jour'])) && isset($_REQUEST['heure']) && isset($_REQUEST['duree']) && ( $duree = call_user_func_array(function ($h,$m) { return intval($h)*60+intval($m); }, array_pad(explode('h',$_REQUEST['duree']),2,0)) ) > 0 )  {
+elseif ( ( $action == 'ajout-notes' ) && ( ( $autorisation == 3 ) || ( $autorisation == 5 ) ) && isset($_REQUEST['matiere']) && in_array($matiere = intval($_REQUEST['matiere']),explode(',',$_SESSION['matieres'])) && isset($_REQUEST['jour']) && strlen($jour = preg_filter('/(\d{2})\/(\d{2})\/(\d{4})/','$3-$2-$1',$_REQUEST['jour'])) && isset($_REQUEST['heure']) && isset($_REQUEST['duree']) )  {
 
   // Connexion normale obligatoire
   connexionlight();
   $mysqli = connectsql(true);
+  // Spécifications pour les manipulations de caractères sur 2 octets (accents)
+  mb_internal_encoding('UTF-8');
 
+  // Vérification de l'heure (non obligatoire : chaîne vide éventuellement)
+  $heure = preg_filter('/(\d{1,2})h(\d{2})/','$1:$2',$_REQUEST['heure']);
+  // Vérification de la durée
+  if ( ( $duree = call_user_func_array(function ($h,$m) { return intval($h)*60+intval($m); }, array_pad(explode('h',$_REQUEST['duree']),2,0)) ) == 0 )
+    exit('{"etat":"nok","message":"La durée saisie ne peut pas être nulle."}');
+
+  // Heures en séances de TD (pas de notes associées)
+  if ( isset($_REQUEST['td']) && isset($_REQUEST['description']) )  {
+    // Vérification que le jour est bien dans l'année
+    $resultat = $mysqli->query("SELECT id FROM semaines WHERE debut <= '$jour' AND debut >= SUBDATE('$jour',7) ORDER BY debut DESC LIMIT 1");
+    if ( !$resultat->num_rows )
+      exit('{"etat":"nok","message":"Le jour choisi ne se trouve pas dans l\'année scolaire. S\'il s\'agit d\'une erreur, il faut peut-être contacter l\'administrateur."}');
+    $resultat->free();
+    // Vérification de la description
+    if ( !strlen($description = trim(htmlspecialchars($_REQUEST['description']))) )
+      exit('{"etat":"nok","message":"Pour les séances de TD sans note, la description de la séance doit obligatoirement être non vide."}');
+    // Écriture dans la table heurescolles
+    if ( requete('heurescolles',"INSERT INTO heurescolles SET colleur = ${_SESSION['id']}, matiere = $matiere, jour = '$jour', heure = '$heure', duree = '$duree', description = '".$mysqli->real_escape_string(mb_strtoupper(mb_substr($description,0,1)).mb_substr($description,1)).'\'',$mysqli) )
+      exit($_SESSION['message'] = '{"etat":"ok","message":"La séance a été ajoutée."}');
+    exit('{"etat":"nok","message":"La séance n\'a pas été ajoutée. Erreur MySQL n°'.$mysqli->errno.', «'.$mysqli->error.'»."}');
+  }
+  
   // Vérification de l'identifiant de la semaine
+  if ( !isset($_REQUEST['sid']) || !ctype_digit($sid = $_REQUEST['sid']) )
+    exit('{"etat":"nok","message":"Semaine non valide"}');
   $resultat = $mysqli->query("SELECT (SELECT GROUP_CONCAT(eleve) FROM notes WHERE semaine = semaines.id AND matiere = $matiere) FROM semaines WHERE id = $sid AND colle");
   if ( !$resultat->num_rows )
-    exit('{"etat":"nok","message":"Identifiant non valide"}');
+    exit('{"etat":"nok","message":"Semaine non valide"}');
   $r = $resultat->fetch_row();
   $resultat->free();
   $dejanotes = $r[0];
@@ -361,9 +433,12 @@
   if ( ( $r[0] < 0 ) || ( ( $resultat->num_rows == 1 ) && ( $r[0] >= 7 ) || ( $r = $resultat->fetch_row() ) && ( $r[0] >= 0 ) ) )
     exit('{"etat":"nok","message":"La date saisie ne se trouve pas dans la semaine choisie."}');
   $resultat->free();
-  // Validation de l'heure (non obligatoire)
-  $heure = preg_filter('/(\d{1,2})h(\d{2})/','$1:$2',$_REQUEST['heure']);
- 
+
+  // Écriture de l'heure dans la table heurescolles
+  if ( !requete('heurescolles',"INSERT INTO heurescolles SET colleur = ${_SESSION['id']}, matiere = $matiere, jour = '$jour', heure = '$heure', duree = '$duree', description = ''",$mysqli) )
+    exit('{"etat":"nok","message":"La colle n\'a pas été ajoutée. Erreur MySQL n°'.$mysqli->errno.', «'.$mysqli->error.'»."}');
+  $heure = $mysqli->insert_id;
+  
   // Récupération des élèves associés à la matière
   $resultat = $mysqli->query("SELECT GROUP_CONCAT(id) FROM utilisateurs WHERE autorisation = 2 AND FIND_IN_SET($matiere,matieres)");
   $r = $resultat->fetch_row();
@@ -371,11 +446,6 @@
   $elevesdispos = array_diff(explode(',',$r[0]),explode(',',$dejanotes));
   $notes = array('0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','0,5','1,5','2,5','3,5','4,5','5,5','6,5','7,5','8,5','9,5','10,5','11,5','12,5','13,5','14,5','15,5','16,5','17,5','18,5','19,5','abs','nn');
 
-  // Écriture de l'heure dans la table heurescolles
-  if ( !requete('heurescolles',"INSERT INTO heurescolles SET colleur = ${_SESSION['id']}, matiere = $matiere, jour = '$jour', heure = '$heure', duree = '$duree'",$mysqli) )
-    exit('{"etat":"nok","message":"La colle n\'a pas été ajoutée. Erreur MySQL n°'.$mysqli->errno.', «'.$mysqli->error.'»."}');
-  $heure = $mysqli->insert_id;
-  
   // Insertion pour les élèves non déjà notés
   $requete = array();
   foreach ( $elevesdispos as $eleve )
@@ -1706,7 +1776,9 @@
         if ( !in_array($login,explode(',',$s[0])) )
           $requete .= ', login = \''.$mysqli->real_escape_string($login).'\'';
       }
-      if ( isset($modifications['mail']) && filter_var($mail = $modifications['mail'],FILTER_VALIDATE_EMAIL) && isset($_REQUEST['mail2']) && ( $mail == mb_strtolower(trim($_REQUEST['mail2'])) ) )  {
+      if ( isset($modifications['mail']) && filter_var($mail = $modifications['mail'],FILTER_VALIDATE_EMAIL) && isset($_REQUEST['mail2']) )  {
+        if ( $mail != mb_strtolower(trim($_REQUEST['mail2'])) )
+          exit('{"etat":"nok","message":"Les préférences '.$compte.' n\'ont pas été modifiées, les deux adresses électroniques saisies ne sont pas identiques."}');
         // Vérification que l'adresse n'existe pas déjà
         $resultat = $mysqli->query("SELECT GROUP_CONCAT(mail) FROM utilisateurs WHERE id != $id AND mail > ''");
         $s = $resultat->fetch_row();
@@ -1758,9 +1830,27 @@
     // Suppression
     case 'supprutilisateur': {
       if ( requete('utilisateurs',"DELETE FROM utilisateurs WHERE id = $id",$mysqli)
-        && requete('groupes',"UPDATE groupes SET utilisateurs = TRIM(BOTH ',' FROM REPLACE(CONCAT(',',utilisateurs,','),',$id,',',')) WHERE FIND_IN_SET($id,utilisateurs)",$mysqli)
-        && requete('notes',"DELETE FROM notes WHERE colleur = $id OR eleve = $id",$mysqli) )
+        && requete('groupes',"UPDATE groupes SET utilisateurs = TRIM(BOTH ',' FROM REPLACE(CONCAT(',',utilisateurs,','),',$id,',',')) WHERE FIND_IN_SET($id,utilisateurs)",$mysqli) )  {
+        // Recherche des notes : cas des colleurs/profs
+        if ( $r['autorisation'] > 2 )  {
+          requete('notes',"DELETE FROM notes WHERE colleur = $id",$mysqli);
+          requete('heurescolles',"DELETE FROM heurescolles WHERE colleur = $id",$mysqli);
+        }
+        // Recherche des notes : cas des élèves
+        elseif ( $r['autorisation'] == 2 )  {
+          $resultat = $mysqli->query("SELECT GROUP_CONCAT(heure) FROM notes WHERE eleve = $id");
+          $s = $resultat->fetch_row();
+          $resultat->free();
+          if ( !is_null($s[0]) )  {
+            requete('notes',"DELETE FROM notes WHERE eleve = $id",$mysqli);
+            requete('heurescolles',"DELETE heurescolles FROM heurescolles LEFT JOIN notes ON heurescolles.id=notes.heure
+                                    WHERE FIND_IN_SET(heurescolles.id,'${s[0]}') AND notes.id IS NULL",$mysqli);
+            requete('heurescolles',"UPDATE heurescolles SET duree = duree-(SELECT dureecolle FROM matieres WHERE matieres.id = heurescolles.matiere) 
+                                    WHERE FIND_IN_SET(heurescolles.id,'${s[0]}') AND releve = 0",$mysqli);
+          }
+        }
         exit($_SESSION['message'] = "{\"etat\":\"ok\",\"message\":\"Compte $compte supprimé\"}");
+      }
       exit("{\"etat\":\"nok\",\"message\":\"La suppression du compte $compte n'a pas été réalisée. Erreur MySQL n°".$mysqli->errno.', «'.$mysqli->error.'»."}');
     }
 
@@ -1847,9 +1937,27 @@
       while ( $r = $resultat->fetch_assoc() )  {
         $compte = ( strlen($r['nom'].$r['prenom']) ) ? "de <em>${r['prenom']} ${r['nom']}</em>" : "<em>${r['login']}</em>";
         if ( requete('utilisateurs',"DELETE FROM utilisateurs WHERE id = ${r['id']}",$mysqli)
-          && requete('groupes',"UPDATE groupes SET utilisateurs = TRIM(BOTH ',' FROM REPLACE(CONCAT(',',utilisateurs,','),',${r['id']},',',')) WHERE FIND_IN_SET(${r['id']},utilisateurs)",$mysqli)
-          && requete('notes',"DELETE FROM notes WHERE colleur = ${r['id']} OR eleve = ${r['id']}",$mysqli) )
+          && requete('groupes',"UPDATE groupes SET utilisateurs = TRIM(BOTH ',' FROM REPLACE(CONCAT(',',utilisateurs,','),',${r['id']},',',')) WHERE FIND_IN_SET(${r['id']},utilisateurs)",$mysqli) )  {
+          // Recherche des notes : cas des colleurs/profs
+          if ( $r['autorisation'] > 2 )  {
+            requete('notes',"DELETE FROM notes WHERE colleur = $id",$mysqli);
+            requete('heurescolles',"DELETE FROM heurescolles WHERE colleur = $id",$mysqli);
+          }
+          // Recherche des notes : cas des élèves
+          elseif ( $r['autorisation'] == 2 )  {
+            $resultat = $mysqli->query("SELECT GROUP_CONCAT(heure) FROM notes WHERE eleve = $id");
+            $s = $resultat->fetch_row();
+            $resultat->free();
+            if ( !is_null($s[0]) )  {
+              requete('notes',"DELETE FROM notes WHERE eleve = $id",$mysqli);
+              requete('heurescolles',"DELETE heurescolles FROM heurescolles LEFT JOIN notes ON heurescolles.id=notes.heure
+                                      WHERE FIND_IN_SET(heurescolles.id,'${s[0]}') AND notes.id IS NULL",$mysqli);
+              requete('heurescolles',"UPDATE heurescolles SET duree = duree-(SELECT dureecolle FROM matieres WHERE matieres.id = heurescolles.matiere) 
+                                      WHERE FIND_IN_SET(heurescolles.id,'${s[0]}') AND releve = 0",$mysqli);
+            }
+          }
           $message['ok'] .= "Le compte $compte a été supprimé.<br>";
+        }
         else
           $message['nok'] .= "Le compte $compte n'a pas été supprimé. Erreur MySQL n°".$mysqli->errno.', «'.$mysqli->error.'»<br>';
       }
@@ -2043,8 +2151,7 @@
   elseif ( $val && requete('utilisateurs',"UPDATE utilisateurs SET matieres = CONCAT(matieres,',$mid') WHERE id = $id",$mysqli) )
     $message = "{\"etat\":\"ok\",\"message\":\"L'utilisateur ${r['nom']} a été associé à la matière $matiere.\"}";
   // Désassociation
-  elseif ( !$val && requete('utilisateurs',"UPDATE utilisateurs SET matieres = TRIM(TRAILING ',' FROM REPLACE(CONCAT(matieres,','),',$mid,',',')) WHERE id = $id",$mysqli)
-                 && requete('notes',"DELETE FROM notes WHERE matiere = $mid AND ( colleur = $id OR eleve = $id)",$mysqli) )
+  elseif ( !$val && requete('utilisateurs',"UPDATE utilisateurs SET matieres = TRIM(TRAILING ',' FROM REPLACE(CONCAT(matieres,','),',$mid,',',')) WHERE id = $id",$mysqli) )
     $message = "{\"etat\":\"ok\",\"message\":\"L'association de l'utilisateur ${r['nom']} à la matière $matiere a été supprimée.\"}";
   else
     exit("{\"etat\":\"nok\",\"message\":\"L'association de l'utilisateur ${r['nom']} à la matière $matiere n'a pas été modifiée. Erreur MySQL n°".$mysqli->errno.', «'.$mysqli->error.'»."}');
@@ -2092,8 +2199,7 @@
     elseif ( $val && requete('utilisateurs',"UPDATE utilisateurs SET matieres = CONCAT(matieres,',$mid') WHERE id = ${r['id']}",$mysqli) )
       $message['ok'] .= "Le compte $compte a été associé à la matière <em>$matiere</em>.<br>";
     // Désassociation
-    elseif ( !$val && requete('utilisateurs',"UPDATE utilisateurs SET matieres = TRIM(TRAILING ',' FROM REPLACE(CONCAT(matieres,','),',$mid,',',')) WHERE id = ${r['id']}",$mysqli)
-                   && requete('notes',"DELETE FROM notes WHERE matiere = $mid AND ( colleur = ${r['id']} OR eleve = ${r['id']})",$mysqli) )
+    elseif ( !$val && requete('utilisateurs',"UPDATE utilisateurs SET matieres = TRIM(TRAILING ',' FROM REPLACE(CONCAT(matieres,','),',$mid,',',')) WHERE id = ${r['id']}",$mysqli) )
       $message['ok'] .= "L'association du compte $compte à la matière <em>$matiere</em> a été supprimée.<br>";
     else
       $message['nok'] .= "L'association de l'utilisateur ${r['nom']} à la matière $matiere n'a pas été modifiée. Erreur MySQL n°".$mysqli->errno.', «'.$mysqli->error.'».<br>';
diff -urN cahier-de-prepa8.0.2/CHANGELOG.php cahier-de-prepa8.1.0/CHANGELOG.php
--- cahier-de-prepa8.0.2/CHANGELOG.php	2018-10-24 00:44:38.514239367 +0200
+++ cahier-de-prepa8.1.0/CHANGELOG.php	2018-10-31 03:59:47.004088147 +0100
@@ -1,4 +1,4 @@
-Version actuelle : 8.0.2 (23/10/18)
+Version actuelle : 8.1.0 (31/10/18)
 ===================
 Changements :
 1.0   31/08/11 Première version
@@ -220,12 +220,15 @@
   * Possibilité de désactiver les fonctions cahier de texte/programme de colle/
     notes de colles : elles disparaissent alors du menu.
 8.0.2 23/10/18 Correction de bugs
-  
+8.1.0 30/10/18 Correction de bugs et améliorations des notes de colles :
+  * Possibilité d'impression du relevé de colles pour le compte administratif
+  * Possibilité de déclaration de séances de cours ou TD sans note 
+
 ===================
 
 Todo :
 
-[8.1] Janvier 2019
+[8.2] Janvier 2019
   * Mode lecture
   * Page de préférences globales : création de compte, protection globale, titre
   * Page de statistiques des colles toutes matières confondues ?
diff -urN cahier-de-prepa8.0.2/css/icones1810.min.css cahier-de-prepa8.1.0/css/icones1810.min.css
--- cahier-de-prepa8.0.2/css/icones1810.min.css	2018-10-18 23:41:26.666214781 +0200
+++ cahier-de-prepa8.1.0/css/icones1810.min.css	1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-@font-face{font-family:'icomoon';src:url('../fonts/icomoon.eot?13');src:url('../fonts/icomoon.eot?#iefix13') format('embedded-opentype'),url('../fonts/icomoon.ttf?13') format('truetype'),url('../fonts/icomoon.woff?13') format('woff'),url('../fonts/icomoon.svg?13#icomoon') format('svg');font-weight:normal;font-style:normal}[class^="icon-"]{font-family:'icomoon'!important;color:black;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a[class^="icon-"]{cursor:pointer;text-decoration:none}span.icon-minilock{position:relative!important;left:-0.3em;top:.1em;color:#777;margin-right:-0.5em}.icon-montre:before{content:"\e600"}.icon-cache:before{content:"\e601"}.icon-aide:before{content:"\e602"}.icon-ajoute:before,.icon-ajoutecolle:before{content:"\e603"}.icon-supprime:before{content:"\e604"}.icon-annule:before{content:"\e605"}.icon-ok:before,.icon-envoidoc:before{content:"\e606"}.icon-prefs:before{content:"\e607"}.icon-monte:before{content:"\e608"}.icon-descend:before{content:"\e609"}.icon-ferme:before{content:"\e60a"}.icon-epingle:before{content:"\e60b"}.icon-par1:before{content:"\e60c"}.icon-par2:before{content:"\e60d"}.icon-par3:before{content:"\e60e"}.icon-gras:before{content:"\e60f"}.icon-italique:before{content:"\e610"}.icon-souligne:before{content:"\e611"}.icon-omega:before{content:"\e612"}.icon-sigma:before{content:"\e613"}.icon-exp:before{content:"\e614"}.icon-ind:before{content:"\e615"}.icon-ol:before{content:"\e616"}.icon-ul:before{content:"\e617"}.icon-lien1:before{content:"\e618"}.icon-lien2:before{content:"\e619"}.icon-retour:before{content:"\e61a"}.icon-source:before{content:"\e61b"}.icon-nosource:before{content:"\e61c"}.icon-tex:before{content:"\e61d"}.icon-titres:before{content:"\e61e"}.icon-edite:before,.icon-editedoc:before,.icon-editerep:before{content:"\e61f"}.icon-precedent:before{content:"\e620"}.icon-suivant:before{content:"\e621"}.icon-recherche:before{content:"\e622"}.icon-voirtout:before{content:"\e623";color:#000}.icon-accueil:before{content:"\e624"}.icon-imprime:before{content:"\e625"}.icon-connexion:before{content:"\e626"}.icon-deconnexion:before{content:"\e627"}.icon-mail:before{content:"\e628"}.icon-menu:before{content:"\e629"}.icon-cocher:before{content:"\e62a"}.icon-decocher:before{content:"\e62b"}.icon-rep:before{content:"\e62c"}.icon-rep-open:before{content:"\e62d"}.icon-download:before{content:"\e62e"}.icon-minilock:before{content:"\e62f"}.icon-alphaasc:before{content:"\e630"}.icon-alphadesc:before{content:"\e631"}.icon-chronoasc:before{content:"\e632"}.icon-chronodesc:before{content:"\e633"}.icon-ajouterep:before{content:"\e634"}.icon-ajoutedoc:before{content:"\e635"}.icon-doc:before{content:"\e636"}.icon-doc-pdf:before{content:"\e637"}.icon-doc-doc:before{content:"\e638"}.icon-doc-xls:before{content:"\e639"}.icon-doc-ppt:before{content:"\e63a"}.icon-doc-jpg:before{content:"\e63b"}.icon-doc-zip:before{content:"\e63c"}.icon-doc-mp3:before{content:"\e63d"}.icon-doc-mp4:before{content:"\e63e"}.icon-doc-pyt:before{content:"\e63f"}.icon-rss:before{content:"\e640"}.icon-infos:before{content:"\e641"}.icon-colles:before{content:"\e642"}.icon-recent:before{content:"\e643"}.icon-lock1:before{content:"\e644"}.icon-lock2:before{content:"\e645"}.icon-lock3:before{content:"\e646"}.icon-lock4:before{content:"\e647"}.icon-lock5:before{content:"\e648"}.icon-agenda:before{content:"\e649"}.icon-ajout-colle:before{content:"\e64a"}.icon-messages:before{content:"\e64b"}.icon-lock:before{content:"\e64c"}.icon-locktotal:before{content:"\e64d"}.icon-editemultiple:before{content:"\e64e"}.icon-plie:before{content:"\e64f"}.icon-deplie:before{content:"\e650"}.icon-mailenvoi:before{content:"\e651"}.icon-nok:before{content:"\e652"}.icon-active:before{content:"\e653"}.icon-desactive:before{content:"\e654"}.icon-supprutilisateur:before{content:"\e655"}.icon-validutilisateur:before{content:"\e656"}.icon-lecture:before{content:"\e657"}.icon-nolecture:before{content:"\e658";
diff -urN cahier-de-prepa8.0.2/css/icones.css cahier-de-prepa8.1.0/css/icones.css
--- cahier-de-prepa8.0.2/css/icones.css	2018-10-18 23:41:02.721935642 +0200
+++ cahier-de-prepa8.1.0/css/icones.css	2018-10-27 22:33:15.519945682 +0200
@@ -1,10 +1,10 @@
 @font-face {
   font-family: 'icomoon';
-  src:url('../fonts/icomoon.eot?13');
-  src:url('../fonts/icomoon.eot?#iefix13') format('embedded-opentype'),
-    url('../fonts/icomoon.ttf?13') format('truetype'),
-    url('../fonts/icomoon.woff?13') format('woff'),
-    url('../fonts/icomoon.svg?13#icomoon') format('svg');
+  src:url('../fonts/icomoon.eot?18');
+  src:url('../fonts/icomoon.eot?#iefix18') format('embedded-opentype'),
+    url('../fonts/icomoon.ttf?18') format('truetype'),
+    url('../fonts/icomoon.woff?18') format('woff'),
+    url('../fonts/icomoon.svg?18#icomoon') format('svg');
   font-weight: normal;
   font-style: normal;
 }
diff -urN cahier-de-prepa8.0.2/css/icones.min.css cahier-de-prepa8.1.0/css/icones.min.css
--- cahier-de-prepa8.0.2/css/icones.min.css	1970-01-01 01:00:00.000000000 +0100
+++ cahier-de-prepa8.1.0/css/icones.min.css	2018-10-31 03:52:49.115198187 +0100
@@ -0,0 +1 @@
+@font-face{font-family:'icomoon';src:url('../fonts/icomoon.eot?18');src:url('../fonts/icomoon.eot?#iefix18') format('embedded-opentype'),url('../fonts/icomoon.ttf?18') format('truetype'),url('../fonts/icomoon.woff?18') format('woff'),url('../fonts/icomoon.svg?18#icomoon') format('svg');font-weight:normal;font-style:normal}[class^="icon-"]{font-family:'icomoon'!important;color:black;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a[class^="icon-"]{cursor:pointer;text-decoration:none}span.icon-minilock{position:relative!important;left:-0.3em;top:.1em;color:#777;margin-right:-0.5em}.icon-montre:before{content:"\e600"}.icon-cache:before{content:"\e601"}.icon-aide:before{content:"\e602"}.icon-ajoute:before,.icon-ajoutecolle:before{content:"\e603"}.icon-supprime:before{content:"\e604"}.icon-annule:before{content:"\e605"}.icon-ok:before,.icon-envoidoc:before{content:"\e606"}.icon-prefs:before{content:"\e607"}.icon-monte:before{content:"\e608"}.icon-descend:before{content:"\e609"}.icon-ferme:before{content:"\e60a"}.icon-epingle:before{content:"\e60b"}.icon-par1:before{content:"\e60c"}.icon-par2:before{content:"\e60d"}.icon-par3:before{content:"\e60e"}.icon-gras:before{content:"\e60f"}.icon-italique:before{content:"\e610"}.icon-souligne:before{content:"\e611"}.icon-omega:before{content:"\e612"}.icon-sigma:before{content:"\e613"}.icon-exp:before{content:"\e614"}.icon-ind:before{content:"\e615"}.icon-ol:before{content:"\e616"}.icon-ul:before{content:"\e617"}.icon-lien1:before{content:"\e618"}.icon-lien2:before{content:"\e619"}.icon-retour:before{content:"\e61a"}.icon-source:before{content:"\e61b"}.icon-nosource:before{content:"\e61c"}.icon-tex:before{content:"\e61d"}.icon-titres:before{content:"\e61e"}.icon-edite:before,.icon-editedoc:before,.icon-editerep:before{content:"\e61f"}.icon-precedent:before{content:"\e620"}.icon-suivant:before{content:"\e621"}.icon-recherche:before{content:"\e622"}.icon-voirtout:before{content:"\e623";color:#000}.icon-accueil:before{content:"\e624"}.icon-imprime:before{content:"\e625"}.icon-connexion:before{content:"\e626"}.icon-deconnexion:before{content:"\e627"}.icon-mail:before{content:"\e628"}.icon-menu:before{content:"\e629"}.icon-cocher:before{content:"\e62a"}.icon-decocher:before{content:"\e62b"}.icon-rep:before{content:"\e62c"}.icon-rep-open:before{content:"\e62d"}.icon-download:before{content:"\e62e"}.icon-minilock:before{content:"\e62f"}.icon-alphaasc:before{content:"\e630"}.icon-alphadesc:before{content:"\e631"}.icon-chronoasc:before{content:"\e632"}.icon-chronodesc:before{content:"\e633"}.icon-ajouterep:before{content:"\e634"}.icon-ajoutedoc:before{content:"\e635"}.icon-doc:before{content:"\e636"}.icon-doc-pdf:before{content:"\e637"}.icon-doc-doc:before{content:"\e638"}.icon-doc-xls:before{content:"\e639"}.icon-doc-ppt:before{content:"\e63a"}.icon-doc-jpg:before{content:"\e63b"}.icon-doc-zip:before{content:"\e63c"}.icon-doc-mp3:before{content:"\e63d"}.icon-doc-mp4:before{content:"\e63e"}.icon-doc-pyt:before{content:"\e63f"}.icon-rss:before{content:"\e640"}.icon-infos:before{content:"\e641"}.icon-colles:before{content:"\e642"}.icon-recent:before{content:"\e643"}.icon-lock1:before{content:"\e644"}.icon-lock2:before{content:"\e645"}.icon-lock3:before{content:"\e646"}.icon-lock4:before{content:"\e647"}.icon-lock5:before{content:"\e648"}.icon-agenda:before{content:"\e649"}.icon-ajout-colle:before{content:"\e64a"}.icon-messages:before{content:"\e64b"}.icon-lock:before{content:"\e64c"}.icon-locktotal:before{content:"\e64d"}.icon-editemultiple:before{content:"\e64e"}.icon-plie:before{content:"\e64f"}.icon-deplie:before{content:"\e650"}.icon-mailenvoi:before{content:"\e651"}.icon-nok:before{content:"\e652"}.icon-active:before{content:"\e653"}.icon-desactive:before{content:"\e654"}.icon-supprutilisateur:before{content:"\e655"}.icon-validutilisateur:before{content:"\e656"}.icon-lecture:before{content:"\e657"}.icon-nolecture:before{content:"\e658";
\ No newline at end of file
diff -urN cahier-de-prepa8.0.2/css/style1810.min.css cahier-de-prepa8.1.0/css/style1810.min.css
--- cahier-de-prepa8.0.2/css/style1810.min.css	2018-10-20 11:20:07.056445528 +0200
+++ cahier-de-prepa8.1.0/css/style1810.min.css	1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-*{font-size:1em;margin:0;padding:0}html,body{height:100%}body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;position:relative;width:100%;margin:0 auto;min-width:320px;max-width:1500px;background-color:#f6f6f6}h1{font-size:2.2em;text-align:center;padding:1em 2em}h2{font-size:1.8em;margin:1em 0 .8em}h3{font-size:1.5em;margin:1em 0 .5em}h2+h3{padding-left:1%}h4{font-size:1.3em;margin:.5em 0 .2em;padding-left:2.5%}h5{font-size:1.1em;margin-top:.2em;padding-left:4%}h6{font-size:1em;margin-top:.2em;padding-left:5.5%}ul,ol{margin:.5em 0;padding:0 2% 0 6%}p{padding:0 2%}p+p{margin-top:.5em}img{border:0;max-width:100%}div,p,section,article{text-align:justify}section>:first-child,article>:first-child,article>h2:first-of-type,article>h3:first-of-type,#fenetre h3:first-of-type{margin-top:0}article>:last-child,#fenetre>:last-child{margin-bottom:0}article{margin-bottom:1em;padding:1em 2%;background-color:#cdd5e4}#fenetre{position:fixed;left:50%;z-index:15;padding:1em 2%;overflow:auto;background-color:#e7eefe;opacity:.97;box-shadow:.5em .5em .5em #777}#fenetre_fond{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#000;opacity:.2;z-index:14}article>a[class^="icon-"],#fenetre>a[class^="icon-"]{float:right;margin-left:.3em}#fenetre hr{margin:1.5em 0}footer{text-align:center;width:90%;padding:1em 5%;clear:both;position:fixed;left:0;bottom:0;z-index:20;border-top:1px solid black;background-color:#DDD;opacity:.97}@media screen and (min-width:800px){#colonne{width:280px;float:left;margin:0 30px 3em}nav{padding:1em 20px .7em}.icon-menu,.icon-recent{display:none}#recent{margin-top:1.5em;padding:1em 20px}section{position:relative;margin:0 30px 0 340px;padding-bottom:3em}#icones{position:absolute;top:-4em;right:0}header+section{width:96%;margin:0 auto;max-width:1500px;text-align:center}footer{font-size:.8em}#fenetre{top:10%;width:70%;margin-left:-37%;max-height:80%}}@media screen and (max-width:800px){h1{font-size:1.8em;padding:.3em 3em}h2{font-size:1.65em}#colonne{display:none}#colonne.visible{display:block}nav.visible,#recent.visible{display:block;position:fixed;z-index:10;top:3.3em;left:.5em;padding:1em 20px .7em;width:80%;min-width:200px;max-width:280px;max-height:70%;overflow:auto;box-shadow:.5em .5em .5em #777}.icon-menu,.icon-recent{position:fixed;z-index:10;top:.8em;left:.5em;font-size:1.2em;cursor:pointer}.icon-recent{left:2.5em}section{position:relative;width:96%;margin:0 auto;padding-bottom:3em}#icones{position:absolute;top:-2.2em;right:0}header+section{text-align:center}footer{font-size:.6em}#fenetre{top:4%;width:92%;margin-left:-48%;max-height:92%}}nav,#recent{background-color:#99b3e5}nav a[class^="icon-"]{display:inline-block;margin:0 .3em;color:#001030}nav a{display:block;margin-bottom:.2em;text-decoration:none;color:#002877}nav a:hover{color:#CDF}nav h3{font-size:1.2em;margin:.5em 3% .1em;padding-top:.3em;color:#001030;border-top:1px solid #001030}nav hr{margin:.5em 3% .5em;color:#001030;border-top:1px solid #001030;border-bottom:0}nav a.menurep{padding-left:3%;font-size:.9em}#actuel{font-style:italic}nav h3 span{font-weight:500;font-size:.83em;margin-right:.2em;color:#001030!important}#recent a{display:block;margin-bottom:.4em;text-decoration:none;color:#002877;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}#recent a span{color:#002877}#recent h3{font-size:1.2em;margin:0 3% .5em;color:#001030}.pdf{height:0;width:100%;overflow:hidden;position:relative}.portrait{padding-bottom:138%}.paysage{padding-bottom:74%}.hauteur50{padding-bottom:50%}.pdf object{position:absolute}.warning{text-align:center;width:50%;margin:1em auto;padding:.5em 3%}.annonce{margin:1em 3%;padding:.5em 4%}.note{margin:.5em 2%;padding:0 4%}.warning,.annonce{color:#ba0d1f;border:2px solid #ba0d1f}.note{color:#ba0d1f}.oubli{font-size:.8em;text-align:center}.oubli a{text-decoration:none;color:#333}.oubli label{font-weight:700}.oubli input{margin-left:1em;vertical-align:text-top}p.titrecdt{text-align:right;text-decoration:underline}p.titrecdt.edition{text-align:left;text-decoration:none;padding-right:1%}.topbarre{height:1.5em;background-color:#DDD;border:1px solid #BBB;width:auto;border-radius:4px;margin-bottom:1.5em}h1 span{font-size:70%;vertical-align:7%;margin-left:.4em}#recherchecdt a,#recherchecolle a,#rechercheagenda a{margin-right:.4em;vertical-align:middle}.topbarre select#semaines{margin-left:.8em;width:8.5em}.topbarre select#seances{margin-left:.8em;width:11em}.topbarre input{position:absolute;top:.25em;margin:0 .8em 0 1em;padding-left:1.8em;width:-moz-available}.topbarre input,.topbarre select{font-size:.9em;height:1.25em;vertical-align:bottom}.topbarre .icon-recherche{position:relative;left:1.9em;font-size:.7em;cursor:pointer}@media screen and (max-width:980px) and (min-width:800px),screen and (max-width:600px){#recherchecdt input{display:none;top:1.8em;padding-left:.1em;right:2em;margin-left:2em!important}#recherchecdt span{left:1.3em}}@media screen and (max-width:450px){#recherchecdt a,#recherchecdt select{margin-left:.3em!important}#recherchecdt input{margin-left:.3em}#recherchecdt select{width:6em!important}#recherchecdt span{left:.3em}}@media screen and (max-width:400px){#recherchecolle a,#recherchecolle select{margin-left:.3em!important}#recherchecolle input{margin-left:0!important}#recherchecolle select{width:6em}#recherchecolle span{left:.3em}}@media screen and (max-width:350px){#recherchecolle input{display:none;top:1.8em;padding-left:.1em;right:2em;margin-left:2em!important}}#parentsdoc{margin-bottom:1.5em;padding:.3em 2% 0;line-height:1.3em}#parentsdoc span{position:static;cursor:auto}.rep,.doc{margin:0 2%;padding:0;border-bottom:1px dotted #BBB;line-height:1.3em}.repcontenu,.docdonnees{float:right;font-size:.8em;padding-left:.5em;line-height:1.625em}#parentsdoc>a[class^="icon-"],.rep>a[class^="icon-"],.doc>a[class^="icon-"]{float:right;margin-left:.3em;line-height:1.3em}#parentsdoc a,.rep a,.doc a{text-decoration:none;color:black}#parentsdoc .nom,.rep .nom,.doc .nom{font-weight:700;margin-left:.5em}.edition{display:inline;text-align:left;padding-right:3em}h3.edition.editable{padding-right:1%}.edition+p,.edition ~ form{margin-top:.75em}article.cache{background-color:#AAA;opacity:.6}#log{position:fixed;top:3%;left:3%;padding:.3em 2%;z-index:20;margin-right:3%}.ok{background-color:#EFE;color:#090;border:1px solid #090}.nok{background-color:#FEE;color:#D00;border:1px solid #D00}.ok span{color:#090}.nok span{color:#D00}#log span{cursor:pointer;position:relative;right:-0.8em;top:.1em}[id^="aide-"],[id^="form-"]{display:none}#fenetre [name="titre"]{margin:2em 0 1em}#fenetre [name="titre"]+*{display:inline}form.titrecdt{padding:.2em 0 .5em;margin-top:.2em}.confirmation{text-align:center}#fenetre.usergrp .ligne{border-bottom:1px dotted #BBB}#fenetre.usergrp input{margin-top:.2em}.protection{font-size:.8em;color:#999}input,select,textarea{box-sizing:border-box;-webkit-box-sizing:border-box;border:1px solid;border-radius:2px;padding:0 .3em}#fichier{border:0;font-size:.8em;height:1.9em}p.ligne label{font-weight:700}p.ligne input,p.ligne select,p.ligne code{width:65%;float:right;margin-left:.2em;font-size:.8em;height:1.6em}p.ligne input[type="checkbox"],p.ligne input[type="radio"]{width:1em}input.ligne{width:96%;margin:.5em 2%;height:1.6em;font-size:.8em;display:block}p.ligne+*{clear:right}.gestion_protection{margin:0!important}.gestion_protection p{margin:0}.gestion_protection input{vertical-align:sub}.supprmultiple{margin-top:.3em;margin-bottom:0!important}table{width:100%;margin:1em 0;border-collapse:collapse;border:medium solid #999}table td{padding:.15em .5%}table th{padding:.15em 3%}table td,table th{border:thin solid #AAA}.centre,#planning,#notes{text-align:center}.centre th{padding:.15em 0}tr[data-id]:hover,#planning tbody tr:hover,#fenetre tbody tr:not(.categorie):hover{background-color:#EFF}#selmult{width:auto;min-width:70%;margin:2em auto;padding-bottom:2em}#selmult td{border:0;padding-left:5%;font-weight:700}#selmult .element td:first-child{padding-left:10%;font-weight:500}#selmult td+td{vertical-align:sub;text-align:center;width:5em;padding:.1em}.editable,.titrecdt.edition,form.titrecdt{border:1px dotted #BBB;position:relative}.editable a[class^="icon-"],p.titrecdt a[class^="icon-"],.maildest a[class^="icon-"]{padding-left:.3em}.avecform{border:none!important}h3.editable a[class^="icon-"],h3 span.editable a[class^="icon-"]{font-weight:500;font-size:.67em;padding-top:.1em}h3.avecform span{font-weight:500;font-size:.6em;margin-top:.5em;width:80%;overflow:hidden;white-space:nowrap}h3.avecform input{width:50%}textarea,[contenteditable=true].ligne{width:96%;margin:.5em 2%}textarea+div{min-height:6em;border:1px dotted #CCC;background-color:#FFF}.boutons{clear:right;background-color:#DDD;border:1px solid #BBB;width:auto;padding:0;margin-bottom:0;border-radius:4px}.boutons button{cursor:default;background-color:transparent;border-top:0;border-left:none;border-bottom:1px solid #BBB;border-right:1px solid #BBB;height:1.5em;font-size:100%;width:2em}.boutons button+button{margin-left:-0.2em}p.boutons.ligne{width:96%;margin:0 2%}[contenteditable=true]:empty:before{content:attr(placeholder);color:#999;font-size:.8em;display:block}div.editable a[class^="icon-"]{position:absolute;right:3px;top:0}div.editable a.icon-annule{top:1.5em}div.edithtml a.icon-ok{top:1.6em}div.edithtml a.icon-annule{top:3.1em}.icon-mailenvoi{font-size:2em}#notes th,#notes td{padding-left:0;padding-right:0}#notes .icones{text-align:left;padding:.15em .5em;width:2.3em}.notes td+td{width:6em;text-align:center}.notes td+td select{width:6em;font-size:.8em;margin-bottom:.2em}td.pasnote{font-style:italic;text-align:center}.collsel{font-weight:700}.collnosel,.dejanote{color:#AAA}#recherchenote{padding:0 1em}#tableaunotes td+td{text-align:right}.sel{background-color:#EFF}#utilisateurs tr,#selmult tr{border-top:0;border-left:none;border-right:0;border-bottom:1px dotted #BBB}#utilisateurs th,#utilisateurs td,#utilisateurs-matieres th,#utilisateurs-matieres td{border:1px dotted #BBB}#fenetre #utilisateurs th,#fenetre #utilisateurs td{border:0}#fenetre #utilisateurs th+th,#fenetre #utilisateurs td+td{text-align:center;width:5em;padding:.1em}#utilisateurs input,#utilisateurs-matieres input,#selmult input{vertical-align:sub}.categorie th+th,#utilisateurs-matieres td+td{text-align:center;padding:0}#utilisateurs .icones{width:1em;white-space:nowrap;padding:.15em .3em;font-weight:normal;text-align:right}#utilisateurs .icones *{font-weight:normal;vertical-align:middle;padding:0;margin:0}#utilisateurs .icones input{width:1em}#utilisateurs .icones a{display:inline-block;width:1em}.categorie th{border:none!important}.categorie span{cursor:pointer}th.semaines,th.matieres,th.colleurs{vertical-align:bottom;padding:1em 0;text-align:center}th.semaines{width:1.7em}th.semaines span,th.matieres span,th.colleurs span{display:inline-block;writing-mode:vertical-lr;-webkit-writing-mode:vertical-lr;transform:rotate(180deg);-webkit-transform:rotate(180deg);white-space:nowrap}@media print{body{font-size:90%;font-family:Serif}#colonne,#recherchecolle,#recherchecdt,#rechercheagenda,[id^="aide-"],[id^="form-"],footer,a[class^="icon-"]{display:none}.editable,.titrecdt.edition,form.titrecdt{border:0}h1{font-size:1.7em}h2{font-size:1.5em;margin:.7em 0}h3{font-size:1.35em;margin:.6em 0}h4{font-size:1.2em;margin:.4em 0 .2em}article{border:1px solid #999}}#calendrier{margin-top:1em}#calendrier table{table-layout:fixed}#semaine,.semaine-bg,.evenements{margin:0}#semaine{font-weight:900;text-align:center}#semaine th{overflow:hidden;text-overflow:clip}.semaine-bg{border-top:0;position:absolute;z-index:1}.autremois{background-color:#e7eefe;color:#002877}#aujourdhui{background-color:#99b3e5}.evenements{position:relative;z-index:2;border-top:0;border-bottom:0}.evenements thead{border-bottom:1px solid #999}.evenements th{padding:.15em .5%;text-align:right}.evenements td{padding:2px 3px 1px;border:none!important}.modifevnmt{padding:1px 3px;border-radius:5px;white-space:nowrap;overflow:hidden;font-size:.8em;cursor:pointer}.evnmt_suivi{border-top-right-radius:0;border-bottom-right-radius:0;margin-right:-2px}.evnmt_suite{border-top-left-radius:0;border-bottom-left-radius:0;margin-left:-3px}#load{display:none;margin:0;padding:0;position:fixed;top:0;left:0;width:100%;height:100%;z-index:30;text-align:center}#load img{position:absolute;top:50%}
diff -urN cahier-de-prepa8.0.2/css/style.css cahier-de-prepa8.1.0/css/style.css
--- cahier-de-prepa8.0.2/css/style.css	2018-10-20 11:19:18.319917357 +0200
+++ cahier-de-prepa8.1.0/css/style.css	2018-10-28 01:06:24.017445327 +0200
@@ -227,10 +227,11 @@
 .icon-mailenvoi { font-size: 2em; }
 
 /* Tableau de notes de colles personnel */
-#notes th, #notes td { padding-left: 0; padding-right: 0; }
+#notes th, #notes td { padding: 0.15em 0.5em; }
 #notes .icones { text-align: left; padding: 0.15em 0.5em; width: 2.3em; }
 .notes td+td { width: 6em; text-align: center; }
 .notes td+td select { width: 6em; font-size: 0.8em; margin-bottom: 0.2em; }
+.notes + p.ligne { clear: right; margin-top: 0.5em; }
 
 /* Tableau de notes global */
 td.pasnote { font-style: italic; text-align: center; }
@@ -272,6 +273,7 @@
   h3 { font-size: 1.35em; margin: 0.6em 0; }
   h4 { font-size: 1.2em; margin: 0.4em 0 0.2em; }
   article { border: 1px solid #999; }
+  table th { padding: 0.15em 0.5%; }
 }
 
 /* Agenda */
diff -urN cahier-de-prepa8.0.2/css/style.min.css cahier-de-prepa8.1.0/css/style.min.css
--- cahier-de-prepa8.0.2/css/style.min.css	1970-01-01 01:00:00.000000000 +0100
+++ cahier-de-prepa8.1.0/css/style.min.css	2018-10-31 03:52:49.351200890 +0100
@@ -0,0 +1 @@
+*{font-size:1em;margin:0;padding:0}html,body{height:100%}body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;position:relative;width:100%;margin:0 auto;min-width:320px;max-width:1500px;background-color:#f6f6f6}h1{font-size:2.2em;text-align:center;padding:1em 2em}h2{font-size:1.8em;margin:1em 0 .8em}h3{font-size:1.5em;margin:1em 0 .5em}h2+h3{padding-left:1%}h4{font-size:1.3em;margin:.5em 0 .2em;padding-left:2.5%}h5{font-size:1.1em;margin-top:.2em;padding-left:4%}h6{font-size:1em;margin-top:.2em;padding-left:5.5%}ul,ol{margin:.5em 0;padding:0 2% 0 6%}p{padding:0 2%}p+p{margin-top:.5em}img{border:0;max-width:100%}div,p,section,article{text-align:justify}section>:first-child,article>:first-child,article>h2:first-of-type,article>h3:first-of-type,#fenetre h3:first-of-type{margin-top:0}article>:last-child,#fenetre>:last-child{margin-bottom:0}article{margin-bottom:1em;padding:1em 2%;background-color:#cdd5e4}#fenetre{position:fixed;left:50%;z-index:15;padding:1em 2%;overflow:auto;background-color:#e7eefe;opacity:.97;box-shadow:.5em .5em .5em #777}#fenetre_fond{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#000;opacity:.2;z-index:14}article>a[class^="icon-"],#fenetre>a[class^="icon-"]{float:right;margin-left:.3em}#fenetre hr{margin:1.5em 0}footer{text-align:center;width:90%;padding:1em 5%;clear:both;position:fixed;left:0;bottom:0;z-index:20;border-top:1px solid black;background-color:#DDD;opacity:.97}@media screen and (min-width:800px){#colonne{width:280px;float:left;margin:0 30px 3em}nav{padding:1em 20px .7em}.icon-menu,.icon-recent{display:none}#recent{margin-top:1.5em;padding:1em 20px}section{position:relative;margin:0 30px 0 340px;padding-bottom:3em}#icones{position:absolute;top:-4em;right:0}header+section{width:96%;margin:0 auto;max-width:1500px;text-align:center}footer{font-size:.8em}#fenetre{top:10%;width:70%;margin-left:-37%;max-height:80%}}@media screen and (max-width:800px){h1{font-size:1.8em;padding:.3em 3em}h2{font-size:1.65em}#colonne{display:none}#colonne.visible{display:block}nav.visible,#recent.visible{display:block;position:fixed;z-index:10;top:3.3em;left:.5em;padding:1em 20px .7em;width:80%;min-width:200px;max-width:280px;max-height:70%;overflow:auto;box-shadow:.5em .5em .5em #777}.icon-menu,.icon-recent{position:fixed;z-index:10;top:.8em;left:.5em;font-size:1.2em;cursor:pointer}.icon-recent{left:2.5em}section{position:relative;width:96%;margin:0 auto;padding-bottom:3em}#icones{position:absolute;top:-2.2em;right:0}header+section{text-align:center}footer{font-size:.6em}#fenetre{top:4%;width:92%;margin-left:-48%;max-height:92%}}nav,#recent{background-color:#99b3e5}nav a[class^="icon-"]{display:inline-block;margin:0 .3em;color:#001030}nav a{display:block;margin-bottom:.2em;text-decoration:none;color:#002877}nav a:hover{color:#CDF}nav h3{font-size:1.2em;margin:.5em 3% .1em;padding-top:.3em;color:#001030;border-top:1px solid #001030}nav hr{margin:.5em 3% .5em;color:#001030;border-top:1px solid #001030;border-bottom:0}nav a.menurep{padding-left:3%;font-size:.9em}#actuel{font-style:italic}nav h3 span{font-weight:500;font-size:.83em;margin-right:.2em;color:#001030!important}#recent a{display:block;margin-bottom:.4em;text-decoration:none;color:#002877;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}#recent a span{color:#002877}#recent h3{font-size:1.2em;margin:0 3% .5em;color:#001030}.pdf{height:0;width:100%;overflow:hidden;position:relative}.portrait{padding-bottom:138%}.paysage{padding-bottom:74%}.hauteur50{padding-bottom:50%}.pdf object{position:absolute}.warning{text-align:center;width:50%;margin:1em auto;padding:.5em 3%}.annonce{margin:1em 3%;padding:.5em 4%}.note{margin:.5em 2%;padding:0 4%}.warning,.annonce{color:#ba0d1f;border:2px solid #ba0d1f}.note{color:#ba0d1f}.oubli{font-size:.8em;text-align:center}.oubli a{text-decoration:none;color:#333}.oubli label{font-weight:700}.oubli input{margin-left:1em;vertical-align:text-top}p.titrecdt{text-align:right;text-decoration:underline}p.titrecdt.edition{text-align:left;text-decoration:none;padding-right:1%}.topbarre{height:1.5em;background-color:#DDD;border:1px solid #BBB;width:auto;border-radius:4px;margin-bottom:1.5em}h1 span{font-size:70%;vertical-align:7%;margin-left:.4em}#recherchecdt a,#recherchecolle a,#rechercheagenda a{margin-right:.4em;vertical-align:middle}.topbarre select#semaines{margin-left:.8em;width:8.5em}.topbarre select#seances{margin-left:.8em;width:11em}.topbarre input{position:absolute;top:.25em;margin:0 .8em 0 1em;padding-left:1.8em;width:-moz-available}.topbarre input,.topbarre select{font-size:.9em;height:1.25em;vertical-align:bottom}.topbarre .icon-recherche{position:relative;left:1.9em;font-size:.7em;cursor:pointer}@media screen and (max-width:980px) and (min-width:800px),screen and (max-width:600px){#recherchecdt input{display:none;top:1.8em;padding-left:.1em;right:2em;margin-left:2em!important}#recherchecdt span{left:1.3em}}@media screen and (max-width:450px){#recherchecdt a,#recherchecdt select{margin-left:.3em!important}#recherchecdt input{margin-left:.3em}#recherchecdt select{width:6em!important}#recherchecdt span{left:.3em}}@media screen and (max-width:400px){#recherchecolle a,#recherchecolle select{margin-left:.3em!important}#recherchecolle input{margin-left:0!important}#recherchecolle select{width:6em}#recherchecolle span{left:.3em}}@media screen and (max-width:350px){#recherchecolle input{display:none;top:1.8em;padding-left:.1em;right:2em;margin-left:2em!important}}#parentsdoc{margin-bottom:1.5em;padding:.3em 2% 0;line-height:1.3em}#parentsdoc span{position:static;cursor:auto}.rep,.doc{margin:0 2%;padding:0;border-bottom:1px dotted #BBB;line-height:1.3em}.repcontenu,.docdonnees{float:right;font-size:.8em;padding-left:.5em;line-height:1.625em}#parentsdoc>a[class^="icon-"],.rep>a[class^="icon-"],.doc>a[class^="icon-"]{float:right;margin-left:.3em;line-height:1.3em}#parentsdoc a,.rep a,.doc a{text-decoration:none;color:black}#parentsdoc .nom,.rep .nom,.doc .nom{font-weight:700;margin-left:.5em}.edition{display:inline;text-align:left;padding-right:3em}h3.edition.editable{padding-right:1%}.edition+p,.edition ~ form{margin-top:.75em}article.cache{background-color:#AAA;opacity:.6}#log{position:fixed;top:3%;left:3%;padding:.3em 2%;z-index:20;margin-right:3%}.ok{background-color:#EFE;color:#090;border:1px solid #090}.nok{background-color:#FEE;color:#D00;border:1px solid #D00}.ok span{color:#090}.nok span{color:#D00}#log span{cursor:pointer;position:relative;right:-0.8em;top:.1em}[id^="aide-"],[id^="form-"]{display:none}#fenetre [name="titre"]{margin:2em 0 1em}#fenetre [name="titre"]+*{display:inline}form.titrecdt{padding:.2em 0 .5em;margin-top:.2em}.confirmation{text-align:center}#fenetre.usergrp .ligne{border-bottom:1px dotted #BBB}#fenetre.usergrp input{margin-top:.2em}.protection{font-size:.8em;color:#999}input,select,textarea{box-sizing:border-box;-webkit-box-sizing:border-box;border:1px solid;border-radius:2px;padding:0 .3em}#fichier{border:0;font-size:.8em;height:1.9em}p.ligne label{font-weight:700}p.ligne input,p.ligne select,p.ligne code{width:65%;float:right;margin-left:.2em;font-size:.8em;height:1.6em}p.ligne input[type="checkbox"],p.ligne input[type="radio"]{width:1em}input.ligne{width:96%;margin:.5em 2%;height:1.6em;font-size:.8em;display:block}p.ligne+*{clear:right}.gestion_protection{margin:0!important}.gestion_protection p{margin:0}.gestion_protection input{vertical-align:sub}.supprmultiple{margin-top:.3em;margin-bottom:0!important}table{width:100%;margin:1em 0;border-collapse:collapse;border:medium solid #999}table td{padding:.15em .5%}table th{padding:.15em 3%}table td,table th{border:thin solid #AAA}.centre,#planning,#notes{text-align:center}.centre th{padding:.15em 0}tr[data-id]:hover,#planning tbody tr:hover,#fenetre tbody tr:not(.categorie):hover{background-color:#EFF}#selmult{width:auto;min-width:70%;margin:2em auto;padding-bottom:2em}#selmult td{border:0;padding-left:5%;font-weight:700}#selmult .element td:first-child{padding-left:10%;font-weight:500}#selmult td+td{vertical-align:sub;text-align:center;width:5em;padding:.1em}.editable,.titrecdt.edition,form.titrecdt{border:1px dotted #BBB;position:relative}.editable a[class^="icon-"],p.titrecdt a[class^="icon-"],.maildest a[class^="icon-"]{padding-left:.3em}.avecform{border:none!important}h3.editable a[class^="icon-"],h3 span.editable a[class^="icon-"]{font-weight:500;font-size:.67em;padding-top:.1em}h3.avecform span{font-weight:500;font-size:.6em;margin-top:.5em;width:80%;overflow:hidden;white-space:nowrap}h3.avecform input{width:50%}textarea,[contenteditable=true].ligne{width:96%;margin:.5em 2%}textarea+div{min-height:6em;border:1px dotted #CCC;background-color:#FFF}.boutons{clear:right;background-color:#DDD;border:1px solid #BBB;width:auto;padding:0;margin-bottom:0;border-radius:4px}.boutons button{cursor:default;background-color:transparent;border-top:0;border-left:none;border-bottom:1px solid #BBB;border-right:1px solid #BBB;height:1.5em;font-size:100%;width:2em}.boutons button+button{margin-left:-0.2em}p.boutons.ligne{width:96%;margin:0 2%}[contenteditable=true]:empty:before{content:attr(placeholder);color:#999;font-size:.8em;display:block}div.editable a[class^="icon-"]{position:absolute;right:3px;top:0}div.editable a.icon-annule{top:1.5em}div.edithtml a.icon-ok{top:1.6em}div.edithtml a.icon-annule{top:3.1em}.icon-mailenvoi{font-size:2em}#notes th,#notes td{padding:.15em .5em}#notes .icones{text-align:left;padding:.15em .5em;width:2.3em}.notes td+td{width:6em;text-align:center}.notes td+td select{width:6em;font-size:.8em;margin-bottom:.2em}.notes+p.ligne{clear:right;margin-top:.5em}td.pasnote{font-style:italic;text-align:center}.collsel{font-weight:700}.collnosel,.dejanote{color:#AAA}#recherchenote{padding:0 1em}#tableaunotes td+td{text-align:right}.sel{background-color:#EFF}#utilisateurs tr,#selmult tr{border-top:0;border-left:none;border-right:0;border-bottom:1px dotted #BBB}#utilisateurs th,#utilisateurs td,#utilisateurs-matieres th,#utilisateurs-matieres td{border:1px dotted #BBB}#fenetre #utilisateurs th,#fenetre #utilisateurs td{border:0}#fenetre #utilisateurs th+th,#fenetre #utilisateurs td+td{text-align:center;width:5em;padding:.1em}#utilisateurs input,#utilisateurs-matieres input,#selmult input{vertical-align:sub}.categorie th+th,#utilisateurs-matieres td+td{text-align:center;padding:0}#utilisateurs .icones{width:1em;white-space:nowrap;padding:.15em .3em;font-weight:normal;text-align:right}#utilisateurs .icones *{font-weight:normal;vertical-align:middle;padding:0;margin:0}#utilisateurs .icones input{width:1em}#utilisateurs .icones a{display:inline-block;width:1em}.categorie th{border:none!important}.categorie span{cursor:pointer}th.semaines,th.matieres,th.colleurs{vertical-align:bottom;padding:1em 0;text-align:center}th.semaines{width:1.7em}th.semaines span,th.matieres span,th.colleurs span{display:inline-block;writing-mode:vertical-lr;-webkit-writing-mode:vertical-rl;transform:rotate(180deg);-webkit-transform:rotate(180deg);white-space:nowrap}@media print{body{font-size:90%;font-family:Serif}#colonne,#recherchecolle,#recherchecdt,#rechercheagenda,[id^="aide-"],[id^="form-"],footer,a[class^="icon-"]{display:none}.editable,.titrecdt.edition,form.titrecdt{border:0}h1{font-size:1.7em}h2{font-size:1.5em;margin:.7em 0}h3{font-size:1.35em;margin:.6em 0}h4{font-size:1.2em;margin:.4em 0 .2em}article{border:1px solid #999}table th{padding:.15em .5%}}#calendrier{margin-top:1em}#calendrier table{table-layout:fixed}#semaine,.semaine-bg,.evenements{margin:0}#semaine{font-weight:900;text-align:center}#semaine th{overflow:hidden;text-overflow:clip}.semaine-bg{border-top:0;position:absolute;z-index:1}.autremois{background-color:#e7eefe;color:#002877}#aujourdhui{background-color:#99b3e5}.evenements{position:relative;z-index:2;border-top:0;border-bottom:0}.evenements thead{border-bottom:1px solid #999}.evenements th{padding:.15em .5%;text-align:right}.evenements td{padding:2px 3px 1px;border:none!important}.modifevnmt{padding:1px 3px;border-radius:5px;white-space:nowrap;overflow:hidden;font-size:.8em;cursor:pointer}.evnmt_suivi{border-top-right-radius:0;border-bottom-right-radius:0;margin-right:-2px}.evnmt_suite{border-top-left-radius:0;border-bottom-left-radius:0;margin-left:-3px}#load{display:none;margin:0;padding:0;position:fixed;top:0;left:0;width:100%;height:100%;z-index:30;text-align:center}#load img{position:absolute;top:50%}
\ No newline at end of file
diff -urN cahier-de-prepa8.0.2/def_sql.php cahier-de-prepa8.1.0/def_sql.php
--- cahier-de-prepa8.0.2/def_sql.php	2018-10-19 00:36:14.708539874 +0200
+++ cahier-de-prepa8.1.0/def_sql.php	2018-10-27 23:56:44.625458730 +0200
@@ -235,6 +235,7 @@
   `jour` date NOT NULL,
   `heure` time NOT NULL,
   `duree` smallint(3) unsigned NOT NULL,
+  `description` varchar(200) NOT NULL,
   `releve` date NOT NULL,
   KEY `colleur` (`colleur`),
   KEY `matiere` (`matiere`)
diff -urN cahier-de-prepa8.0.2/fonctions.php cahier-de-prepa8.1.0/fonctions.php
--- cahier-de-prepa8.0.2/fonctions.php	2018-10-20 02:21:45.484001552 +0200
+++ cahier-de-prepa8.1.0/fonctions.php	2018-10-31 04:00:11.408376567 +0100
@@ -715,8 +715,8 @@
   <title>$head</title>
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0">
-  <link rel="stylesheet" href="css/style1810.min.css">
-  <link rel="stylesheet" href="css/icones1810.min.css">$css
+  <link rel="stylesheet" href="css/style.min.css?v=810">
+  <link rel="stylesheet" href="css/icones.min.css?v=810">$css
   <script type="text/javascript" src="js/jquery.min.js"></script>
   <link rel="alternate" type="application/rss+xml" title="Flux RSS" href="documents/rss/$rss/rss.xml">
 </head>
@@ -739,7 +739,7 @@
 <script type="text/javascript" src="/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
 <script type="text/x-mathjax-config">MathJax.Hub.Config({tex2jax:{inlineMath:[["$","$"],["\\\\(","\\\\)"]]}});</script>' : '';
   // Édition possible si $edition est true
-  $js = ( $edition ) ? '<script type="text/javascript" src="js/edition.min18.js"></script>' : '<script type="text/javascript" src="js/fonctions.min18.js"></script>';
+  $js = ( $edition ) ? '<script type="text/javascript" src="js/edition.min.js?v=810"></script>' : '<script type="text/javascript" src="js/fonctions.min.js?v=810"></script>';
   // Affichage de message si $_SESSION['message']
   if ( isset($_SESSION['message']) )  {
     $m = json_decode($_SESSION['message'],true);
diff -urN cahier-de-prepa8.0.2/installation.php cahier-de-prepa8.1.0/installation.php
--- cahier-de-prepa8.0.2/installation.php	2018-10-17 00:49:29.425459813 +0200
+++ cahier-de-prepa8.1.0/installation.php	2018-10-31 11:27:21.732088029 +0100
@@ -11,8 +11,8 @@
   <title>Cahier de Prépa&nbsp;: installation</title>
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0">
-  <link rel="stylesheet" href="css/style1810.min.css">
-  <link rel="stylesheet" href="css/icones1810.min.css">
+  <link rel="stylesheet" href="css/style.min.css">
+  <link rel="stylesheet" href="css/icones.min.css">
   <script type="text/javascript" src="js/jquery.min.js"></script>
   <style>
     p.ligne { padding: 0 2%; }
diff -urN cahier-de-prepa8.0.2/js/edition.js cahier-de-prepa8.1.0/js/edition.js
--- cahier-de-prepa8.0.2/js/edition.js	2018-10-20 02:18:19.817599033 +0200
+++ cahier-de-prepa8.1.0/js/edition.js	2018-10-30 23:30:32.437052507 +0100
@@ -1064,17 +1064,17 @@
   switch ( prop[0] ) {
     case 'infos': item = 'une information'; break;
     case 'pages': item = 'la matière <em>'+$('h3', parent).text()+'</em>. Les informations qui y sont écrites seront aussi supprimées'; break;
-    case 'reps': item = 'le répertoire <em>'+$('.nom', parent).map(function() { return this.textContent || $(this).find('input').val(); }).get(0)+'</em>. Tous les sous-répertoires et documents qui s\'y trouvent seront aussi supprimés'; break;
+    case 'reps': item = 'le répertoire <em>'+$('.nom', parent).map(function() { return this.textContent || $(this).find('input').val(); }).get(0)+'</em>. <strong>Tous les sous-répertoires et documents qui s\'y trouvent seront aussi supprimés</strong>'; break;
     case 'docs': item = 'le document <em>'+$('.nom', parent).map(function() { return this.textContent || $(this).find('input').val(); }).get(0)+'</em>'; break;
     case 'colles': item = 'le programme de colle de la '+$('.edition',parent).text().toLowerCase(); break;
     case 'cdt-elems': item = 'un élément du cahier de texte'; break;
-    case 'cdt-types': item = 'le type de séances <em>'+$('h3', parent).text()+'</em>. Les éléments du cahier de texte associés à ce type seront aussi supprimés'; break;
+    case 'cdt-types': item = 'le type de séances <em>'+$('h3', parent).text()+'</em>. <strong>Les éléments du cahier de texte associés à ce type seront aussi supprimés</strong>'; break;
     case 'cdt-raccourcis': item = 'le raccourci de séance <em>'+$('h3', parent).text()+'</em>. Aucun élément du cahier de texte ne sera supprimé'; break;
-    case 'notes': parent = parent.parent(); item = 'une colle du <em>'+$('td:first',parent).text()+'</em>, d\'une durée de '+$('td:eq(3)',parent).text()+'. Toutes les notes associées seront supprimées'; break;
-    case 'matieres': item = 'la matière <em>'+$('h3', parent).text()+'</em>. Les programmes de colles, le cahier de texte et les notes correspondantes seront supprimées. Les répertoires, les documents, les pages d\'informations spécifiques et les éléments de l\'agenda associés à la matière seront conservés mais ne seront plus associés à une matières, donc visibles dans le contexte «&nbsp;général&nbsp;»'; break;
+    case 'notes': parent = parent.parent(); item = 'une colle ou séance sans note du <em>'+$('td:first',parent).text()+'</em>, d\'une durée de '+$('td:eq(3)',parent).text()+'. Toutes les notes de cette colle seront supprimées'; break;
+    case 'matieres': item = 'la matière <em>'+$('h3', parent).text()+'</em>. <p class="note"><strong>ATTENTION&nbsp;: Les programmes de colles, le cahier de texte et les notes correspondantes seront toutes automatiquement supprimées.</strong></p> <p>Les répertoires, les documents, les pages d\'informations spécifiques et les éléments de l\'agenda associés à la matière seront conservés mais ne seront plus associés à une matière&nbsp;: ils seront désormais visibles dans le contexte «&nbsp;général&nbsp;».<br><strong>Si vous souhaitez simplement réinitialiser la matière, ce n\'est pas la bonne méthode</strong>&nbsp;: vous devriez pouvoir faire ce que vous souhaitez avec les possibilités de cette page'; break;
     case 'groupes': item = 'le groupe <em>'+( $('.editable', parent).text() || $('input:first', parent).val())+'</em>. Les utilisateurs concernés ne seront pas supprimés'; break;
     case 'agenda-elems': item = 'un événement de l\'agenda'; break;
-    case 'agenda-types': item = 'le type d\'événement <em>'+$('h3', parent).text()+'</em>. Les événements de l\'agenda associés à ce type seront aussi supprimés'; break;
+    case 'agenda-types': item = 'le type d\'événement <em>'+$('h3', parent).text()+'</em>. <strong>Les événements de l\'agenda associés à ce type seront aussi supprimés</strong>'; break;
   }
   confirmation('Vous allez supprimer XXX.<br>Cette opération n\'est pas annulable.'.replace('XXX',item),this,function(el) {
     $.ajax({url: 'ajax.php',
@@ -1289,7 +1289,7 @@
       this.value = nettoie( ( $(this).is(':visible') ) ? this.value : $(this).next().html() );
     });
     // Nettoyage des notes à ne pas mettre
-    if ( ( action == 'notes' ) || ( action == 'ajoute-notes' ) )
+    if ( ( action == 'notes' ) || ( action == 'ajout-notes' ) )
       $('#epingle select:not(:visible)').val('x');
     // Envoi
     $.ajax({url: 'ajax.php',
@@ -1421,8 +1421,10 @@
               // Réécriture du message de log (état ok), suppression de la
               // fermeture automatique : le message reste visible pendant 
               // tout le téléchargement.
-              window.clearTimeout(extinction);
-              $('#log').html('Envoi du document. Cela peut prendre du temps...');
+              if ( $('#fichier')[0].files.length > 0 ) {
+                window.clearTimeout(extinction);
+                $('#log').html('Envoi du document. Cela peut prendre du temps...');
+              }
               // Envoi réel du fichier ou des données
               var data = new FormData(form[0]);
               // Envoi
@@ -1565,28 +1567,29 @@
 $.fn.init_notes = function(action) {
   var el = $(this);
   var form = $('#epingle form').append($('#form-notes').html());
+  var table = $('table',form);
   // Création de l'identifiant des champs à partir du name
   $('input, select',form).attr('id',function(){ return this.getAttribute('name'); });
   
   // Génération des select de notes
-  $('tr[data-id]',form).append('<td>'+$('div',form).html()+'</td>');
-  $('table select',form).attr('name',function() {
+  $('tr[data-id]',table).append('<td>'+$('div',form).html()+'</td>');
+  $('select',table).attr('name',function() {
     return 'e'+$(this).parent().parent().data('id');
   });
   $('div',form).remove();
   
   // On cache tous les élèves a priori s'il y a des groupes
-  if ( $('input:checkbox',form).length ) {
+  if ( $('input:checkbox',table).length ) {
     $('tr[data-id]',form).hide();
     // Clic sur les groupes
-    $('input:checkbox', form).on("click", function () {
-      if ( $('input:checkbox:last', form).prop('checked') )
+    $('input:checkbox', table).on("change", function () {
+      if ( $('input:checkbox:last', table).prop('checked') )
         return $('tr[data-id]',form).show();
       // Récupération des élèves du groupe
-      var ids = $('input:checked', form).map(function() { return this.value.split(','); }).get().concat();
+      var ids = $('input:checked', table).map(function() { return this.value.split(','); }).get().concat();
       // On cache tous les élèves sauf ceux ayant déjà une note pour l'édition
       // de notes déjà saisies (lignes repérées par la classe "orig")
-      $('tr[data-id]:not(.orig)',form).hide();
+      $('tr[data-id]:not(.orig)',table).hide();
       for (var i=0; i<ids.length; i++)
         $('tr[data-id="'+ids[i]+'"]',form).show();
     });
@@ -1615,80 +1618,116 @@
 
   // Facilités
   $('#jour').datetimepicker({ format: 'd/m/Y', timepicker: false, onShow: function() {
-      this.setOptions({ minDate: debut || $('#sid option:selected').data('date') ,
-                        maxDate: new Date( new Date(( fin || $('#sid option:selected').next().data('date') ).replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z) {return z+'-'+y+'-'+x; })).getTime()-86400000 ) });
+      if ( $('#td').is(':checked') )
+        this.setOptions({ minDate: $('#form-ajoute option:eq(1)').data('date') ,
+                          maxDate: new Date( new Date(( $('#form-ajoute option:last').data('date') ).replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z) {return z+'-'+y+'-'+x; })).getTime()+6*86400000 ) });
+      else
+        this.setOptions({ minDate: debut || $('#sid option:selected').data('date') ,
+                          maxDate: new Date( new Date(( fin || $('#sid option:selected').next().data('date') ).replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z) {return z+'-'+y+'-'+x; })).getTime()-86400000 ) });
     }
   });
   $('#heure').datetimepicker({ format: 'Ghi', datepicker: false, defaultTime: '15h30' });
   $('#duree').datetimepicker({ format: 'Ghi', datepicker: false, defaultTime: '0h00', step: 10 })
              .on("change", function() { $(this).removeClass('auto'); });
-  // Changement de semaine : seulement ajout de notes
-  $('#sid').on("change keyup", function() {
-    // Nettoyage des déjà notés précédents
-    $('.dejanote td:first-child').text( function() {
-      return this.textContent.replace(' (noté par un autre colleur)','').replace(' (déjà noté par vous-même)','');
-    });
-    $('.dejanote').removeClass('dejanote').find('select').prop('disabled',false);
-    // Marquage des déjà notés
-    marque_dejanotes($('#sid').val());
-    // Réglage du jour si hors de la semaine
-    var jour = new Date($('#jour').val().replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z) {return z+'-'+y+'-'+x; }));
-    var debut = new Date($('#sid option:selected').data('date').replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z) {return z+'-'+y+'-'+x; }));
-    var fin = new Date($('#sid option:selected').next().data('date').replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z) {return z+'-'+y+'-'+x; }));
-    if ( ( jour < debut ) || ( jour > fin ) ) {
-      debut = debut.toJSON();
-      $('#jour').val(debut.substr(8,2)+'/'+debut.substr(5,2)+'/'+debut.substr(0,4));
-    }
-  }).change();
-  // Mise à jour de la durée
-  $('select', form).on("change keyup", function() {
+  // Mise à jour de la durée à chaque nouvelle note
+  $('select', table).on("change keyup", function() {
     var nb = $('table select:visible',form).filter(function() { return this.value != "x"; }).length;
     var duree = nb*(dureecolle || 20);
     if ( $('#duree').is('.auto') || duree > $('#duree').val().replace(/^(\d*)h(\d*)$/,function(tout,x,y) {return 60*(x|0)+(y|0); }) )
       $('#duree').val( (duree/60|0)+'h'+(duree%60||'') ).addClass('auto');
   });
 
+  // Si nouvelles notes : gestion du changement de semaine et
+  // de la possibilité de séance de TD
+  if ( action == 'ajout-notes' ) {
+    // Changement de semaine
+    $('#sid').on("change keyup", function() {
+      // Nettoyage des déjà notés précédents
+      $('.dejanote td:first-child').text( function() {
+        return this.textContent.replace(' (noté par un autre colleur)','').replace(' (déjà noté par vous-même)','');
+      });
+      $('.dejanote').removeClass('dejanote').find('select').prop('disabled',false);
+      // Marquage des déjà notés
+      marque_dejanotes($('#sid').val());
+      // Réglage du jour si hors de la semaine
+      var jour = new Date($('#jour').val().replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z) {return z+'-'+y+'-'+x; }));
+      var debut = new Date($('#sid option:selected').data('date').replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z) {return z+'-'+y+'-'+x; }));
+      var fin = new Date($('#sid option:selected').next().data('date').replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z) {return z+'-'+y+'-'+x; }));
+      if ( ( jour < debut ) || ( jour > fin ) ) {
+        debut = debut.toJSON();
+        $('#jour').val(debut.substr(8,2)+'/'+debut.substr(5,2)+'/'+debut.substr(0,4));
+      }
+    }).change();
+    // Gestion des séances de TD
+    $('#td').on("change keyup",function () {
+      if ( this.checked ) {
+        $('#sid').parent().hide();
+        $('#description').parent().show();
+        table.hide();
+      }
+      else {
+        $('#sid').parent().show();
+        $('#description').parent().hide();
+        table.show();
+      }
+    });
+    $('#description').parent().hide();
+  }
   // Si édition de notes : affichage des notes modifiables, ajout ou modification
   // de la durée possible seulement pour les colles non encore relevées. 
-  // Modification de semaine impossible
-  if ( action == 'notes' ) {
+  else {
     var tr = el.parent().parent();
-    // Récupération des données : semaine, début, fin pour l'utilisation globale
-    // dans le onShow de #jour et dans marque_dejanotes.
-    var sid = el.data('sid');
-    var debut = $('select[name="sid"] option[value="'+sid+'"]').data('date');
-    var fin = $('select[name="sid"] option[value="'+sid+'"]').next().data('date');
-    // Affichage des notes déjà mises. Les lignes sont marquées avec la classe
-    // orig pour rester affichées lors du clic sur une checkbox de groupe, mais
-    // ce marquage est supprimé à la première modification de la note
-    var eleves = el.data('eleves').split('|');
-    var notes = el.data('notes').split('|');
-    for (var i=0; i<eleves.length; i++)
-      $('tr[data-id="'+eleves[i]+'"]', form).addClass('orig').show()
-        .find('select').val(notes[i]).on('change',function() {
-          $(this).parent().parent().removeClass('orig');
-        });
-    // Initialisation du titre, de l'identifiant, du jour, de l'heure, de la durée
-    $('h3',form).text('Modifier des notes - semaine du '+$('select[name="sid"] option[value="'+sid+'"]').text().split(' ').slice(0,3).join(' '));
+    // Cas des colles classiques : semaine spécifiée
+    if ( el.data('sid') ) {
+      $('#description, #td').parent().remove();
+      // Récupération des données : semaine, début, fin pour l'utilisation globale
+      // dans le onShow de #jour et dans marque_dejanotes.
+      var sid = el.data('sid');
+      var debut = $('#form-ajoute option[value="'+sid+'"]').data('date');
+      var fin = $('#form-ajoute option[value="'+sid+'"]').next().data('date');
+      // Affichage des notes déjà mises. Les lignes sont marquées avec la classe
+      // orig pour rester affichées lors du clic sur une checkbox de groupe, mais
+      // ce marquage est supprimé à la première modification de la note
+      var eleves = el.data('eleves').split('|');
+      var notes = el.data('notes').split('|');
+      for (var i=0; i<eleves.length; i++)
+        $('tr[data-id="'+eleves[i]+'"]', form).addClass('orig').show()
+          .find('select').val(notes[i]).on('change',function() {
+            $(this).parent().parent().removeClass('orig');
+          });
+      // Initialisation du titre
+      $('h3',form).text('Modifier des notes - semaine du '+$('select[name="sid"] option[value="'+sid+'"]').text().split(' ').slice(0,3).join(' '));
+      // Si colle non déjà relevée (icône de suppression), on peut tout modifier
+      if ( el.next().length )
+        // Marquage des déjà notés de la semaine
+        marque_dejanotes(sid);
+      // Si colle déjà relevée : on ne peut pas ajouter/supprimer des notes ni
+      // modifier la durée
+      else {
+        $('tr:not(.orig), .orig option[value="x"]',table).remove();
+        $('#duree').prop('disabled',true);
+        form.append('<p>Cette colle a déjà été relevée&nbsp;: il est impossible de modifier quels élèves ont été interrogés ou la durée de la colle. Vous pouvez corriger la date et l\'heure (dans la limite de la semaine enregistrée) ou les notes que vous avez mises vous pouvez mettre une note à un élève initialement absent qui a rattrapé sa colle.</p>');
+      }
+    }
+    // Pas de note d'élève : on supprime le tableau et on récupère la description
+    else {
+      table.remove();
+      $('#td').prop("checked",true).prop("disabled",true);
+      $('#description').val(el.parent().prev().prev().prev().text());
+      // Initialisation du titre
+      $('h3',form).text('Modifier la séance de TD sans note');
+      // Si colle déjà relevée, on ne peut pas modifier la durée
+      if ( el.next().length == 0 ) {
+        $('#duree').prop('disabled',true);
+        form.append('<p>Cette séance a déjà été relevée&nbsp;: il est impossible de modifier sa durée. Vous pouvez corriger la date, l\'heure ou la description.</p>');
+      }
+    }
+    // Initialisation de l'identifiant, du jour, de l'heure, de la durée
     $('#id').val(el.parent().data('id').split('|')[1]);
     $('#jour').val($('td:eq(0)',tr).text().replace(/(.{6})(.{2})/,function(tout,x,y) {return x+'20'+y; }));
     $('#heure').val($('td:eq(1)',tr).text().replace('-',''));
     $('#duree').val($('td:eq(3)',tr).text());
-    // Si colle non déjà relevée (pas d'icône de suppression), on peut tout modifier
-    if ( el.next().length ) {
-      // Marquage des déjà notés de la semaine
-      marque_dejanotes(sid);
-    }
-    // Si colle déjà relevée : on ne peut pas ajouter/supprimer des notes ni
-    // modifier la durée
-    else {
-      $('tr:not(.orig)',form).hide();
-      $('.orig option[value="x"]',form).remove();
-      $('#duree').prop('disabled',true);
-      form.append('<p>Cette colle a déjà été relevée&nbsp;: il est impossible de modifier quels élèves ont été interrogés ou la durée de la colle. Vous pouvez corriger la date et l\'heure (dans la limite de la semaine enregistrée) ou les notes que vous avez mises vous pouvez mettre une note à un élève initialement absent qui a rattrapé sa colle.</p>');
-    }
   }
-
 }
 
 // Facilités spécifiques du formulaire d'ajout d'utilisateurs
@@ -1979,14 +2018,13 @@
     var question = '';
     var compte = $(this).parent().siblings().first().text();
     compte = ( compte.length ) ? 'de <em>'+compte+'</em>' : 'd\'identifiant <em>'+$(this).parent().siblings().first().next().text()+'</em>';
-    //var categorie = $(this).parent().parent().prevUntil('.categorie').last().prev().text();
-    var categorie = $(this).parent().parent().prevUntil('.categorie').last().data('val');
+    var categorie = $(this).parent().parent().prevUntil('.categorie').last().prev().text().split(' ')[0];
     switch ( this.className.substring(5) ) {
       case 'desactive':
         if ( categorie == 'Invités' )
           question = 'Vous allez désactiver le compte invité '+compte+'. Cela signifie que le compte ne sera pas supprimé mais sera non utilisable pour une connexion. Les associations éventuelles avec les matières seront conservées. Ce compte sera listé dans la partie inférieure du tableau.';
         else 
-          question = 'Vous allez désactiver le compte '+compte+'. Cela signifie que le compte sera toujours visible pour les professeurs mais que l\'utilisateur correspondant ne pourra plus se connecter. Les notes de colles éventuelles seront conservées. Les données associées au compte seront conservées. Les accès spécifiques éventuels pourront être rétablis en réactivant le compte. Ce compte sera listé dans la partie inférieure du tableau.';
+          question = 'Vous allez désactiver le compte '+compte+'. Cela signifie que le compte sera toujours visible pour les professeurs mais que l\'utilisateur correspondant ne pourra plus se connecter. <strong>Les notes de colles éventuelles seront conservées. Les données associées au compte seront conservées.</strong><br> Les accès spécifiques éventuels pourront être rétablis en réactivant le compte.<br> Ce compte sera listé dans la partie inférieure du tableau.<br> Cette possibilité est particulièrement utile pour un élève ou un colleur parti en cours d\'année et dont il faut conserver les notes de colles.';
         break;
       case 'active':
         if ( categorie == 'Invités' )
@@ -1996,24 +2034,28 @@
         break;
       case 'supprutilisateur':
         if ( categorie == 'Demandes' )
-          question = 'Vous allez supprimer la demande '+compte+'. Cela signifie que cette demande ne conduira pas à une création de compte. Le demandeur ne sera pas prévenu de votre décision. Une fois réalisée, cette opération est définitive.';
-        else if ( categorie == 'Invitations' )
-          question = 'Vous allez supprimer l\'invitation '+compte+'. Cela signifie que cette invitation ne sera plus valable et que si la personne invitée clique sur le lien reçu par courriel, une erreur apparaîtra devant elle. Cette invitation n\'a pas de délai&nbsp;: il est inutile de supprimer l\'invitation pour la refaire, à moins de s\'être trompé d\'adresse électronique. La personne invitée ne sera pas prévenue de votre décision. Une fois réalisée, cette opération est définitive.';
+          question = 'Vous allez supprimer la demande '+compte+'. Cela signifie que cette demande ne conduira pas à une création de compte. Le demandeur ne sera pas prévenu de votre décision.<br> Une fois réalisée, cette opération est définitive, mais rien n\'empêche le demandeur d\'effectuer une nouvelle demande.<br> <strong>Si vous n\'attendez plus de nouvelle demande de création de compte, il est certainement préférable de supprimer cette possibilité à l\'aide du réglage accessible en cliquant sur l\'icône <span class="icon-prefs"></span> en haut à droite sur cette page</strong>';
+        else if ( categorie == 'Invitations' ) {
+          var textecolles = ( $(this).parent().prev().prev().text() == 'Élève' ) ? '<p class="note"><strong>ATTENTION : toutes les notes de colles qui ont déjà pu être déclarées sur ce compte seront supprimées. Cette suppression est définitive.</strong></p><p>' : '<br>';
+          question = 'Vous allez supprimer l\'invitation '+compte+'. Cela signifie que cette invitation ne sera plus valable et que si la personne invitée clique sur le lien reçu par courriel, une erreur apparaîtra devant elle.'+textecolles+'<strong>L\'invitation envoyée n\'a pas de date de péremption&nbsp;: il est n\'est pas normal de supprimer l\'invitation pour la refaire, à moins de s\'être trompé d\'adresse électronique. Si la personne invitée vous dit ne pas réussir à s\'identifier, proposez-lui de passer par le lien <em>Mot de passe oublié</em>.</strong><br> La personne invitée ne sera pas prévenue de votre décision.';
+        }
         else if ( categorie == 'Professeurs' )
-          question = 'Vous allez supprimer le compte professeur '+compte+'. Cela signifie que toutes les préférences de ce compte seront perdues, ainsi que les éventuelles notes de colles. Les données des matières auxquelles il est associé sont indépendantes&nbsp;: elles ne seront pas supprimées. Une fois réalisée, cette opération est définitive.';
-        else if ( categorie == 'Administatifs' )
-          question ='Vous allez supprimer le compte administratif '+compte+'. Cela signifie que toutes les préférences de ce compte seront perdues. Une fois réalisée, cette opération est définitive.';
+          question = 'Vous allez supprimer le compte professeur '+compte+'. <strong>Cela signifie que toutes les préférences de ce compte seront perdues, ainsi que les éventuelles notes de colles.</strong> <p class="note"><strong>Supprimer un compte pour le recréer n\'est pas la bonne méthode pour réinitialiser un compte,</strong></p><p> par exemple si l\'utilisateur du compte vous indique ne pas arriver à se connecter. Dans ce cas, proposez-lui de passer par le lien <em>Mot de passe oublié</em>. Vous pouvez modifier sur la <a href="utilisateurs">gestion des utilisateurs</a> les nom, prénom, identifiant de connexion et adresse électronique de chaque utilisateur.<br> Pour conserver les données de l\'utilisateur mais lui empêcher la connexion, vous pouvez désactiver le compte en cliquant sur <span class="icon-desactive"></span>.<br> Les données des matières auxquelles il est associé sont indépendantes&nbsp;: elles ne seront pas supprimées.';
+        else if ( categorie == 'Administratifs' )
+          question ='Vous allez supprimer le compte administratif '+compte+'. Cela signifie que toutes les préférences de ce compte seront perdues.';
         else if ( categorie == 'Colleurs' )
-          question = 'Vous allez supprimer le compte colleur '+compte+'. Cela signifie que toutes les préférences de ce compte seront perdues, ainsi que les éventuelles notes de colles. Une fois réalisée, cette opération est définitive.';
+          question = 'Vous allez supprimer le compte colleur '+compte+'. <strong>Cela signifie que toutes les préférences de ce compte seront perdues, ainsi que les éventuelles notes de colles.</strong> <p class="note"><strong>Supprimer un compte pour le recréer n\'est pas la bonne méthode pour réinitialiser un compte,</strong></p><p> par exemple si l\'utilisateur du compte vous indique ne pas arriver à se connecter. Dans ce cas, proposez-lui de passer par le lien <em>Mot de passe oublié</em>. Vous pouvez modifier sur la <a href="utilisateurs">gestion des utilisateurs</a> les nom, prénom, identifiant de connexion et adresse électronique de chaque utilisateur.<br> Pour conserver les données de l\'utilisateur mais lui empêcher la connexion, vous pouvez désactiver le compte en cliquant sur <span class="icon-desactive"></span>.';
         else if ( categorie == 'Élèves' )
-          question = 'Vous allez supprimer le compte élève '+compte+'. Cela signifie que toutes les données correspondant à ce compte seront perdues. Les groupes où il apparaît seront modifiés, les notes de colles éventuelles seront supprimées. Une fois réalisée, cette opération est définitive.';
+          question = 'Vous allez supprimer le compte élève '+compte+'. <strong>Cela signifie que toutes les données correspondant à ce compte seront perdues. Les groupes où il apparaît seront modifiés, les notes de colles éventuelles seront supprimées.</strong> <p class="note"><strong>ATTENTION : toutes les notes de colles qui ont déjà pu être déclarées sur ce compte seront supprimées. Cette suppression est définitive.<br> Supprimer un compte pour le recréer n\'est pas la bonne méthode pour réinitialiser un compte,</strong></p><p> par exemple si l\'utilisateur du compte vous indique ne pas arriver à se connecter. Dans ce cas, proposez-lui de passer par le lien <em>Mot de passe oublié</em>. Vous pouvez modifier sur la <a href="utilisateurs">gestion des utilisateurs</a> les nom, prénom, identifiant de connexion et adresse électronique de chaque utilisateur.<br> Pour conserver les données de l\'utilisateur mais lui empêcher la connexion, vous pouvez désactiver le compte en cliquant sur <span class="icon-desactive"></span>.';
         else if ( categorie == 'Invités' )
-          question ='Vous allez supprimer le compte invité '+compte+'. Cela signifie que la connexion par ce compte ne sera plus possible. Une fois réalisée, cette opération est définitive.';
+          question ='Vous allez supprimer le compte invité '+compte+'. Cela signifie que la connexion par ce compte ne sera plus possible.';
         else
-          question = 'Vous allez supprimer le compte '+compte+' déjà désactivé. Cela signifie que toutes les données correspondant à ce compte seront perdues définitivement. Les groupes où il apparaît seront modifiés, les notes de colles éventuelles seront supprimées. Dans le cas d\'un compte professeur, les données des matières associées ne seront pas supprimées. Une fois réalisée, cette opération est définitive.';
+          question = 'Vous allez supprimer le compte '+compte+' déjà désactivé. <strong>Cela signifie que toutes les données correspondant à ce compte seront perdues définitivement. Les groupes où il apparaît seront modifiés, les notes de colles éventuelles seront supprimées.</strong>';
+        if ( categorie != 'Demandes' )
+          question = question + '<br>Une fois réalisée, cette opération est définitive.';
         break;
       case 'validutilisateur':
-        question = 'Vous allez valider la demande '+compte+'. Son compte sera immédiatement actif et un courriel va immédiatement être envoyé pour le/la prévenir. Il sera automatiquement associé à toutes les matières, pensez à aller supprimer les matières qui ne le concernent pas sur la page de gestion des associations utilisateurs-matières.';
+        question = 'Vous allez valider la demande '+compte+'. Son compte sera immédiatement actif et un courriel va immédiatement être envoyé pour le/la prévenir.<br> Il sera automatiquement associé à toutes les matières&nbsp;: <strong>pensez à aller supprimer les matières qui ne le concernent pas sur la page de gestion des associations utilisateurs-matières.</strong>';
     }
     confirmation(question, this, function(el) {
       $.ajax({url: 'ajax.php',
@@ -2071,7 +2113,9 @@
         if ( categorie == 'Invités' )
           question = 'Vous allez désactiver les comptes invités '+comptes+'. Cela signifie que ces compte ne seront pas supprimés mais seront non utilisables pour une connexion. Les associations éventuelles avec les matières seront conservées. Ces comptes seront listés dans la partie inférieure du tableau.';
         else 
-          question = 'Vous allez désactiver les comptes de '+comptes+'. Cela signifie que ces comptes seront toujours visibles pour les professeurs mais que les utilisateurs correspondant ne pourront plus se connecter. Les notes de colles éventuelles seront conservées. Les données associées aux comptes seront conservées. Les accès spécifiques éventuels pourront être rétablis en réactivant les comptes. Ces comptes seront listés dans la partie inférieure du tableau.';
+          question = 'Vous allez désactiver le compte '+compte+'. Cela signifie que le compte sera toujours visible pour les professeurs mais que l\'utilisateur correspondant ne pourra plus se connecter. <strong>Les notes de colles éventuelles seront conservées. Les données associées au compte seront conservées.</strong><br> Les accès spécifiques éventuels pourront être rétablis en réactivant le compte.<br> Ce compte sera listé dans la partie inférieure du tableau.<br> Cette possibilité est particulièrement utile pour un élève ou un colleur parti en cours d\'année dont il faut conserver les notes de colles.';
+
+          question = 'Vous allez désactiver les comptes de '+comptes+'. Cela signifie que ces comptes seront toujours visibles pour les professeurs mais que les utilisateurs correspondant ne pourront plus se connecter. <strong>Les notes de colles éventuelles seront conservées. Les données associées aux comptes seront conservées.</strong><br> Les accès spécifiques éventuels pourront être rétablis en réactivant les comptes.<br> Ces comptes seront listés dans la partie inférieure du tableau.<br> Cette possibilité est particulièrement utile pour des élèves ou des colleurs partis en cours d\'année et dont il faut conserver les notes de colles.';
         break;
       case 'active':
         if ( categorie == 'Invités' )
@@ -2081,24 +2125,27 @@
         break;
       case 'supprutilisateur':
         if ( categorie == 'Demandes' )
-          question = 'Vous allez supprimer les demandes de '+comptes+'. Cela signifie que ces demandes ne conduiront pas à des créations de compte. Les demandeurs ne seront pas prévenus de votre décision. Une fois réalisée, cette opération est définitive.';
-        else if ( categorie == 'Invitations' )
-          question = 'Vous allez supprimer les invitations de '+comptes+'. Cela signifie que ces invitations ne seront plus valables et que si les personnes invitées cliquent sur le lien reçu par courriel, une erreur apparaîtra devant elles. Ces invitations n\'ont pas de délai&nbsp;: il est inutile de supprimer une invitation pour la refaire, à moins de s\'être trompé d\'adresse électronique. Les personnes invitées ne seront pas prévenues de votre décision. Une fois réalisée, cette opération est définitive.';
+          question = 'Vous allez supprimer les demandes de '+comptes+'. Cela signifie que ces demandes ne conduiront pas à des créations de compte. Les demandeurs ne seront pas prévenus de votre décision.<br> Une fois réalisée, cette opération est définitive, mais rien n\'empêche les demandeurs d\'effectuer une nouvelle demande.<br> <strong>Si vous n\'attendez plus de nouvelle demande de création de compte, il est certainement préférable de supprimer cette possibilité à l\'aide du réglage accessible en cliquant sur l\'icône <span class="icon-prefs"></span> en haut à droite sur cette page</strong>';
+        else if ( categorie == 'Invitations' ) {
+          question = 'Vous allez supprimer les invitations de '+comptes+'. Cela signifie que ces invitations ne seront plus valables et que si les personnes invitées cliquent sur le lien reçu par courriel, une erreur apparaîtra devant elles. <p class="note"><strong>ATTENTION : toutes les notes de colles qui ont déjà pu être déclarées sur les comptes de types élèves seront supprimées. Ces suppressions sont définitives.</strong></p> <p><strong>Ces invitations envoyées n\'ont pas de date de péremption&nbsp;: il n\'est pas normal de supprimer une invitation pour la refaire, à moins de s\'être trompé d\'adresse électronique. Si une personne invitée vous dit ne pas réussir à s\'identifier, proposez-lui de passer par le lien <em>Mot de passe oublié</em>.</strong><br> Les personnes invitées ne seront pas prévenues de votre décision.';
+        }
         else if ( categorie == 'Professeurs' )
-          question = 'Vous allez supprimer les comptes professeurs de '+comptes+'. Cela signifie que toutes les préférences de ces comptes seront perdues, ainsi que les éventuelles notes de colles. Les données des matières auxquelles ils sont associés sont indépendantes&nbsp;: elles ne seront pas supprimées. Une fois réalisée, cette opération est définitive.';
+          question = 'Vous allez supprimer les comptes professeurs de '+comptes+'. <strong>Cela signifie que toutes les préférences de ces comptes seront perdues, ainsi que les éventuelles notes de colles.</strong> <p class="note"><strong>Supprimer un compte pour le recréer n\'est pas la bonne méthode pour réinitialiser un compte,</strong></p><p> par exemple si l\'utilisateur d\'un compte vous indique ne pas arriver à se connecter. Dans ce cas, proposez-lui de passer par le lien <em>Mot de passe oublié</em>. Vous pouvez modifier sur la <a href="utilisateurs">gestion des utilisateurs</a> les nom, prénom, identifiant de connexion et adresse électronique de chaque utilisateur.<br> Pour conserver les données d\'un utilisateur mais lui empêcher la connexion, vous pouvez désactiver le compte en cliquant sur <span class="icon-desactive"></span>.<br> Les données des matières auxquelles ces utilisateurs sont associés sont indépendantes&nbsp;: elles ne seront pas supprimées.';
         else if ( categorie == 'Administratifs' )
-          question ='Vous allez supprimer les comptes administratifs de '+comptes+'. Cela signifie que toutes les préférences de ces comptes seront perdues. Une fois réalisée, cette opération est définitive.';
+          question ='Vous allez supprimer les comptes administratifs de '+comptes+'. Cela signifie que toutes les préférences de ces comptes seront perdues.';
         else if ( categorie == 'Colleurs' )
-          question = 'Vous allez supprimer les comptes colleurs de '+comptes+'. Cela signifie que toutes les préférences de ces comptes seront perdues, ainsi que les éventuelles notes de colles. Une fois réalisée, cette opération est définitive.';
+          question = 'Vous allez supprimer les comptes colleurs de '+comptes+'. <strong>Cela signifie que toutes les préférences de ces comptes seront perdues, ainsi que les éventuelles notes de colles.</strong> <p class="note"><strong>Supprimer un compte pour le recréer n\'est pas la bonne méthode pour réinitialiser un compte,</strong></p><p> par exemple si l\'utilisateur d\'un compte vous indique ne pas arriver à se connecter. Dans ce cas, proposez-lui de passer par le lien <em>Mot de passe oublié</em>. Vous pouvez modifier sur la <a href="utilisateurs">gestion des utilisateurs</a> les nom, prénom, identifiant de connexion et adresse électronique de chaque utilisateur.<br> Pour conserver les données d\'un utilisateur mais lui empêcher la connexion, vous pouvez désactiver le compte en cliquant sur <span class="icon-desactive"></span>.';
         else if ( categorie == 'Élèves' )
-          question = 'Vous allez supprimer les comptes élèves de '+comptes+'. Cela signifie que toutes les données correspondant à ces comptes seront perdues. Les groupes où ils apparaîssent seront modifiés, les notes de colles éventuelles seront supprimées. Une fois réalisée, cette opération est définitive.';
+          question = 'Vous allez supprimer les comptes élèves de '+comptes+'. <strong>Cela signifie que toutes les données correspondant à ces comptes seront perdues. Les groupes où ils apparaissent seront modifiés, les notes de colles éventuelles seront supprimées.</strong> <p class="note"><strong>ATTENTION : toutes les notes de colles qui ont déjà pu être déclarées sur ces compte seront supprimées. Cette suppression est définitive.<br> Supprimer un compte pour le recréer n\'est pas la bonne méthode pour réinitialiser un compte,</strong></p><p> par exemple si l\'utilisateur d\'un compte vous indique ne pas arriver à se connecter. Dans ce cas, proposez-lui de passer par le lien <em>Mot de passe oublié</em>. Vous pouvez modifier sur la <a href="utilisateurs">gestion des utilisateurs</a> les nom, prénom, identifiant de connexion et adresse électronique de chaque utilisateur.<br> Pour conserver les données d\'un utilisateur mais lui empêcher la connexion, vous pouvez désactiver le compte en cliquant sur <span class="icon-desactive"></span>.';
         else if ( categorie == 'Invités' )
-          question ='Vous allez supprimer les comptes invités de '+comptes+'. Cela signifie que la connexion par ces comptes ne sera plus possible. Une fois réalisée, cette opération est définitive.';
+          question ='Vous allez supprimer les comptes invités de '+comptes+'. Cela signifie que la connexion par ces comptes ne sera plus possible.';
         else
-          question = 'Vous allez supprimer les comptes de '+comptes+' déjà désactivés. Cela signifie que toutes les données correspondant à ces comptes seront perdues définitivement. Les groupes où ils apparaîssent seront modifiés, les notes de colles éventuelles seront supprimées. Dans le cas des comptes professeurs, les données des matières associées ne seront pas supprimées. Une fois réalisée, cette opération est définitive.';
+          question = 'Vous allez supprimer les comptes de '+comptes+' déjà désactivés. <strong>Cela signifie que toutes les données correspondant à ces comptes seront perdues définitivement. Les groupes où ils apparaîssent seront modifiés, les notes de colles éventuelles seront supprimées. Dans le cas des comptes professeurs, les données des matières associées ne seront pas supprimées.</strong>';
+        if ( categorie != 'Demandes' )
+          question = question + '<br>Une fois réalisée, cette opération est définitive.';
         break;
       case 'validutilisateur':
-        question = 'Vous allez valider les demandes de '+comptes+'. Leurs comptes seront immédiatement actifs et un courriel va immédiatement leur être envoyé pour les prévenir. Ils seront automatiquement associés à toutes les matières, pensez à aller supprimer les matières qui ne les concernent pas sur la page de gestion des associations utilisateurs-matières.';
+        question = 'Vous allez valider les demandes de '+comptes+'. Leurs comptes seront immédiatement actifs et un courriel va immédiatement leur être envoyé pour les prévenir.<br> Ils seront automatiquement associés à toutes les matières&nbsp;: <strong>pensez à aller supprimer les matières qui ne les concernent pas sur la page de gestion des associations utilisateurs-matières.</strong>';
     }
     confirmation(question, this, function(el) {
       $.ajax({url: 'ajax.php',
diff -urN cahier-de-prepa8.0.2/js/edition.min18.js cahier-de-prepa8.1.0/js/edition.min18.js
--- cahier-de-prepa8.0.2/js/edition.min18.js	2018-10-20 02:21:18.559687036 +0200
+++ cahier-de-prepa8.1.0/js/edition.min18.js	1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
-function affiche(message,etat){$("#log").removeClass().addClass(etat).html(message).append('<span class="icon-ferme"></span>').fadeIn().off("click").on("click",function(){window.clearTimeout(extinction);$(this).fadeOut(800)});extinction=window.setTimeout(function(){$("#log").fadeOut(800)},6e3)}function reconnect(settings,light){$("#fenetre,#fenetre_fond").remove();if(settings.url=="recup.php")var action=settings.data.indexOf("prefs")?"récupérer les préférences de cet utilisateur":"récupérer la liste des répertoires et documents disponibles";else{var action="valider cette action";settings.afficheform=Function.prototype}if(light)popup('<a class="icon-ok" title="Valider"></a><h3>Connexion nécessaire</h3>           <p>Vous êtes déjà connecté, mais vous devez saisir de nouveau votre mot de passe pour '+action+'.</p>           <form>           <p class="ligne"><label for="motdepasse">Mot de passe&nbsp;: </label><input type="password" name="motdepasse" id="motdepasse"></p>           </form>',true);else popup('<a class="icon-ok" title="Valider"></a><h3>Connexion nécessaire</h3>           <p>Vous avez été automatiquement déconnecté. Vous devez vous connecter à nouveau pour '+action+'.</p>           <form>           <p class="ligne"><label for="login">Identifiant&nbsp;: </label><input type="text" name="login" id="login"></p>           <p class="ligne"><label for="motdepasse">Mot de passe&nbsp;: </label><input type="password" name="motdepasse" id="motdepasse"></p>           </form>',true);$("#fenetre input:first").focus();$("#fenetre a.icon-ok").on("click",function(){$.ajax({url:settings.url,method:"post",data:$("#fenetre form").serialize()+"&"+settings.data,dataType:"json",el:settings.el,afficheform:settings.afficheform,fonction:settings.fonction}).done(function(data){if(data["etat"]!="mdpnok")$("#fenetre,#fenetre_fond").remove()})});$("#fenetre a.icon-ferme").on("click",function(){affiche("Modification non effectuée, connexion nécessaire","nok")});$("#fenetre input").on("keypress",function(e){if(e.which==13){$("#fenetre a.icon-ok").click();return false}})}function popup(contenu,modal){$("#fenetre,#fenetre_fond").remove();var el=$('<article id="fenetre"></article>').appendTo("body").html(contenu).focus();if(modal)$('<div id="fenetre_fond"></div>').appendTo("body").click(function(){$("#fenetre,#fenetre_fond").remove()});else $('<a class="icon-epingle" title="Épingler à la page"></a>').prependTo(el).on("click",function(){$("#fenetre_fond").remove();$(this).remove();el.removeAttr("id").insertBefore($("article,#calendrier,#parentsdoc+*").first())});$('<a class="icon-ferme" title="Fermer"></a>').prependTo(el).on("click",function(){el.remove();$("#fenetre_fond").remove()})}function confirmation(question,element,action){popup("<h3>Demande de confirmation</h3><p>"+question+'</p><p class="confirmation"><button class="icon-ok"></button>&nbsp;&nbsp;&nbsp;<button class="icon-annule"></button></p>',true);$("#fenetre .icon-ok").on("click",function(){action(element);$("#fenetre,#fenetre_fond").remove()});$("#fenetre .icon-annule").on("click",function(){$("#fenetre,#fenetre_fond").remove()})}function plie(){$(this).parent().parent().nextUntil(".categorie").fadeToggle("slow");$(this).toggleClass("icon-plie icon-deplie")}$.fn.textareahtml=function(){this.each(function(){var ta=$(this);var placeholder=this.getAttribute("placeholder");this.setAttribute("placeholder",placeholder+". Formattage en HTML, balises visibles.");var ce=$('<div contenteditable="true" placeholder="'+placeholder+'"></div>').insertAfter(ta.before(boutons)).hide();var boutonretour=ta.prev().children(".icon-retour");if(ta.hasClass("ligne")){ce.addClass("ligne");ta.prev().addClass("ligne")}ta.on("keypress",function(e){if(e.which==13)this.value=nettoie(this.value)}).on("paste cut",function(){var el=this;setTimeout(function(){el.value=nettoie(el.value)},100)});ce.on("keypress",function(e){if(e.which==13)boutonretour.click()}).on("paste cut",function(){var el=this;setTimeout(function(){el.innerHTML=nettoie(el.innerHTML)+"<br>"},100)});ta.prev().children(".icon-nosource").on("click",function(e){e.preventDefault();ta.hide();ce.show().css("min-height",ta.outerHeight());$(this).hide().prev().show();ce.focus().html(nettoie(ta.val())).change();if(window.getSelection){var r=document.createRange();r.selectNodeContents(ce[0]);r.collapse(false);var s=window.getSelection();s.removeAllRanges();s.addRange(r)}else{var r=document.body.createTextRange();r.moveToElementText(ce[0]);r.collapse(false);r.select()}});ta.prev().children(".icon-source").on("click",function(e){e.preventDefault();ce.hide(0);ta.show(0).css("height",ce.height());$(this).hide().next().show();ta.focus().val(nettoie(ce.html()))}).hide();ta.prev().children(".icon-aide").on("click",function(e){e.preventDefault();aidetexte()});ta.prev().children().not(".icon-nosource,.icon-source,.icon-aide").on("click",function(e){e.preventDefault();window["insertion_"+this.className.substring(5)]($(this))})})};$.fn.editinplace=function(){this.each(function(){var el=$(this);el.data("original",el.is("h3")?el.text():el.html());$('<a class="icon-edite" title="Modifier"></a>').appendTo(el).on("click",transforme)})};function transforme(){var el=$(this).parent().addClass("avecform");if(el.is("div"))el.html('<form><textarea name="val" rows="'+(el.data("original").split(/\r\n|\r|\n/).length+3)+'"></textarea></form>');else el.html('<form class="edition" onsubmit="$(this).children(\'a.icon-ok\').click(); return false;"><input type="text" name="val" value=""></form>');var input=el.find('[name="val"]').val(el.data("original")).attr("placeholder",el.attr("placeholder"));if(el.hasClass("edithtml"))input.textareahtml();$('<a class="icon-ok" title="Valider"></a>').appendTo(el.children()).on("click",function(){var id=el.data("id").split("|");if(el.hasClass("edithtml"))input.val(nettoie(input.is(":visible")?input.val():input.next().html()));$.ajax({url:"ajax.php",method:"post",data:{action:id[0],champ:id[1],id:id[2],val:input.val()},dataType:"json",el:el,fonction:function(el){var val=el.find('[name="val"]').val();el.removeClass("avecform").html(val).data("original",val);$('<a class="icon-edite" title="Modifier"></a>').appendTo(el).on("click",transforme)}})});$('<a class="icon-annule" title="Annuler"></a>').appendTo(el.children()).on("click",function(){el.removeClass("avecform").html(el.data("original"));$('<a class="icon-edite" title="Modifier"></a>').appendTo(el).on("click",transforme)});input.focus().val(el.hasClass("edithtml")?nettoie(input.val()):input.val())}$.fn.editinplacecdt=function(){this.each(function(){$(this).wrapInner("<span></span>").data("original",$(this).text());$('<a class="icon-edite" title="Modifier"></a>').appendTo($(this)).on("click",transformecdt)})};function transformecdt(){var el=$(this).parent();$(".icon-edite",el).remove();var form=$('<form class="titrecdt"></form>').insertBefore(el.parent().children("div")).html($("#form-cdt").html());$("input, select",form).attr("id",function(){return this.getAttribute("name")});var valeurs=el.data("donnees");for(var cle in valeurs)$("#"+cle).val(valeurs[cle]);form.init_cdt_boutons();$("input,#demigroupe",form).on("change keyup",function(){var t=new Date($("#jour").val().replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z){return z+"-"+y+"-"+x}));var dg=$("#demigroupe").val()==1?" (en demi-groupe)":"";switch(parseInt(seances[$("#tid").val()])){case 0:var titre=jours[t.getDay()]+" "+$("#jour").val()+" à "+$("#h_debut").val()+" : "+$("#tid option:selected").text()+dg;break;case 1:var titre=jours[t.getDay()]+" "+$("#jour").val()+" de "+$("#h_debut").val()+" à "+$("#h_fin").val()+" : "+$("#tid option:selected").text()+dg;break;case 2:var titre=jours[t.getDay()]+" "+$("#jour").val()+" : "+$("#tid option:selected").text()+" pour le "+$("#pour").val()+dg;break;case 3:var titre=jours[t.getDay()]+" "+$("#jour").val()+" : "+$("#tid option:selected").text()+dg;break;case 4:var titre=jours[t.getDay()]+" "+$("#jour").val();break;case 5:var titre="[Entrée hebdomadaire]"}$("span",el).text(titre)});$('<a class="icon-ok" title="Valider"></a>').appendTo(el).on("click",function(){var id=el.parent().data("id").split("|");$.ajax({url:"ajax.php",method:"post",data:"action=cdt-elems&id="+id[1]+"&"+form.serialize(),dataType:"json",el:el,fonction:function(el){var form=el.siblings("form");el.data("original",$("span",el).text()).data("donnees",{tid:$("#tid").val(),jour:$("#jour").val(),h_debut:$("#h_debut").val(),h_fin:$("#h_fin").val(),pour:$("#pour").val(),demigroupe:$("#demigroupe").val()});form.remove();$("a",el).remove();$('<a class="icon-edite" title="Modifier"></a>').appendTo(el).on("click",transformecdt)}}).done(function(data){if(data["etat"]=="ok"&&data["reload"]=="oui")location.reload(true)})});$('<a class="icon-annule" title="Annuler"></a>').appendTo(el).on("click",function(){form.remove();$("span",el).html(el.data("original"));$("a",el).remove();$('<a class="icon-edite" title="Modifier"></a>').appendTo(el).on("click",transformecdt)})}function nettoie(html){if(html.indexOf("cdptmp")>0){var tmp=$("<div>"+html+"</div>");tmp.find(".cdptmp").contents().unwrap();html=tmp.html();if(html.indexOf("cdptmp")>0)html=html.replace(/<span class="cdptmp"><\/span>/g,"")}return html.replace(/(<\/?[A-Z]+)([^>]*>)/g,function(tout,x,y){return x.toLowerCase()+y}).replace(/[\r\n ]+/g," ").replace(/(<br>)+[ ]?<\/(p|div|li|h)/g,function(tout,x,y){return"</"+y}).replace(/<br>/g,"<br>\n").replace(/<(p|div|li|h)/g,function(x){return"\n"+x}).replace(/<\/(p|div|li|h.)>/g,function(x){return x+"\n"}).replace(/<\/?(ul|ol)[^>]*>/g,function(x){return"\n"+x+"\n"}).replace(/^(?!(<p|<div|<ul|<ol|<li|<h))(.+)<br>$/gm,function(tout,x,y){return"<p>"+y+"</p>"}).replace(/^(?!(<(p|div|ul|ol|li)))[ ]?(.+)[ ]?$/gm,function(t,x,y,z){return z.match(/.*(p|div|ul|ol|li|h.)>$/)?z:"<p>"+z+"</p>"}).replace(/^[ ]?(<\/?(br|p|div|h.)>){0,2}[ ]?(<\/(p|div|h.)>)?[ ]?$/gm,"").replace(/^\n/gm,"").replace(/<li/g,"  <li")}function insert(el,debut,fin,milieu){var contenant=el.parent().siblings("textarea,[contenteditable]").filter(":visible")[0];if(!contenant.hasAttribute("data-selection"))marqueselection(el);var texte=milieu===undefined?debut+"Í"+contenant.getAttribute("data-selection")+"Ì"+fin:debut+"Í"+milieu+"Ì"+fin;var contenu=nettoie(contenant.getAttribute("data-contenu").replace(/Í.*Ì/,texte));if(contenant.tagName=="TEXTAREA")contenant.value=contenu.replace(/[ÍÌ]/g,"");else contenant.innerHTML=contenu.replace(/[ÍÌ]/g,"");marqueselection(el,true);if(contenant.tagName=="TEXTAREA"&&contenant.selectionStart!==undefined){contenant.selectionStart=contenu.indexOf("Í");contenant.selectionEnd=contenu.indexOf("Ì")-1;contenant.focus()}else if(document.selection){if(contenant.tagName!="TEXTAREA")contenu=contenu.replace(/(<([^>]+)>)[\n]*/g,"");range=document.body.createTextRange();range.moveToElementText(contenant);range.collapse(true);range.moveEnd("character",contenu.indexOf("Ì")-1);range.moveStart("character",contenu.indexOf("Í"));range.select()}else if(window.getSelection){contenant.innerHTML=contenu.replace("Í",'<span class="cdptmp">').replace("Ì","</span>")+"<br>";selection=window.getSelection();range=document.createRange();range.selectNodeContents($(contenant).find(".cdptmp")[0]);selection.removeAllRanges();selection.addRange(range);contenant.focus()}}function marqueselection(el,efface){var contenant=el.parent().siblings("textarea,[contenteditable]").filter(":visible")[0];if(efface){contenant.removeAttribute("data-selection");contenant.removeAttribute("data-contenu");return true}var original=contenant.tagName=="TEXTAREA"?contenant.value:contenant.innerHTML;var sel="";if(contenant.tagName=="TEXTAREA"&&contenant.selectionStart!==undefined){contenant.focus();sel=contenant.value.substring(contenant.selectionStart,contenant.selectionEnd);contenant.value=contenant.value.substr(0,contenant.selectionStart)+"Í"+sel+"Ì"+contenant.value.substring(contenant.selectionEnd)}else if(window.getSelection){var range=window.getSelection().getRangeAt(0);if(contenant==range.commonAncestorContainer||$.contains(contenant,range.commonAncestorContainer)){var sel=window.getSelection().toString();range.deleteContents();range.insertNode(document.createTextNode("Í"+sel+"Ì"))}}else{var range=document.selection.createRange();if(contenant==range.parentElement()||$.contains(contenant,range.parentElement())){var sel=document.selection.createRange().text;document.selection.createRange().text="Í"+sel+"Ì"}}if(contenant.tagName=="TEXTAREA"){var contenu=contenant.value;contenant.value=original}else{var contenu=contenant.innerHTML;$(contenant).html(original)}if(contenu.indexOf("Ì")<0)contenu=contenu+"ÍÌ";contenant.setAttribute("data-selection",sel);contenant.setAttribute("data-contenu",contenu);return sel}var boutons='<p class="boutons">  <button class="icon-titres" title="Niveaux de titres"></button>  <button class="icon-par1" title="Paragraphe"></button>  <button class="icon-par2" title="Paragraphe important"></button>  <button class="icon-par3" title="Paragraphe très important"></button>  <button class="icon-retour" title="Retour à la ligne"></button>  <button class="icon-gras" title="Gras"></button>  <button class="icon-italique" title="Italique"></button>  <button class="icon-souligne" title="Souligné"></button>  <button class="icon-omega" title="Insérer une lettre grecque"></button>  <button class="icon-sigma" title="Insérer un signe mathématique"></button>  <button class="icon-exp" title="Exposant"></button>  <button class="icon-ind" title="Indice"></button>  <button class="icon-ol" title="Liste énumérée"></button>  <button class="icon-ul" title="Liste à puces"></button>  <button class="icon-lien1" title="Lien vers un document du site"></button>  <button class="icon-lien2" title="Lien internet"></button>  <button class="icon-tex" title="LATEX!"></button>  <button class="icon-source" title="Voir et éditer le code html"></button>  <button class="icon-nosource" title="Voir et éditer le texte formaté"></button>  <button class="icon-aide" title="Aide pour cet éditeur de texte"></button></p>';function insertion_titres(el){popup('<a class="icon-ok" title="Valider"></a><h3>Insertion d\'un titre</h3>  <p>Choisissez le type du titre ci-dessous. Vous pouvez éventuellement modifier le texte (ou pourrez le faire ultérieurement). Il est conseillé d\'utiliser des titres de niveau 2 pour les titres dans les programmes de colle.</p>  <input type="radio" name="titre" id="t3" value="3" checked><h3><label for="t3">Titre de niveau 1 (pour les I,II...)</label></h3><br>  <input type="radio" name="titre" id="t4" value="4"><h4><label for="t4">Titre de niveau 2 (pour les 1,2...)</label></h4><br>  <input type="radio" name="titre" id="t5" value="5"><h5><label for="t5">Titre de niveau 3 (pour les a,b...)</label></h5><br>  <input type="radio" name="titre" id="t6" value="6"><h6><label for="t6">Titre de niveau 4</label></h6><br>  <p class="ligne"><label for="texte">Texte&nbsp;: </label><input type="text" id="texte" value="'+marqueselection(el)+'" size="80"></p>  <hr><h3>Aperçu</h3><div id="apercu"></div>',true);$("#fenetre input").on("click keyup",function(){var balise="h"+$("[name='titre']:checked").val();$("#apercu").html("<"+balise+">"+($("#texte").val().length?$("#texte").val():"Texte du titre")+"</"+balise+">")}).first().keyup();$("#texte").on("keypress",function(e){if(e.which==13)$("#fenetre a.icon-ok").click()}).focus();$("#fenetre a.icon-ok").on("click",function(){var balise="h"+$("[name='titre']:checked").val();insert(el,"<"+balise+">","</"+balise+">",$("#texte").val());$("#fenetre,#fenetre_fond").remove()});$("#fenetre a.icon-ferme,#fenetre_fond").on("click",function(){marqueselection(el,true)})}function insertion_omega(el){popup("<h3>Insertion d'une lettre grecque</h3>  <p>Cliquez sur la lettre à insérer&nbsp;:</p>  <button>&alpha;</button> <button>&beta;</button> <button>&gamma;</button> <button>&Delta;</button> <button>&delta;</button> <button>&epsilon;</button> <button>&eta;</button> <button>&Theta;</button> <button>&theta;</button> <button>&Lambda;</button> <button>&lambda;</button> <button>&mu;</button> <button>&nu;</button> <button>&xi;</button> <button>&Pi;</button> <button>&pi;</button> <button>&rho;</button> <button>&Sigma;</button> <button>&sigma;</button> <button>&tau;</button> <button>&upsilon;</button> <button>&Phi;</button> <button>&phi;</button> <button>&Psi;</button> <button>&psi;</button> <button>&Omega;</button> <button>&omega;</button>",true);$("#fenetre button").on("click",function(){insert(el,"","",$(this).text());$("#fenetre,#fenetre_fond").remove()})}function insertion_sigma(el){popup("<h3>Insertion d'un symbole mathématique</h3>  <p>Cliquez sur le symbole à insérer&nbsp;:</p>  <button>&forall;</button> <button>&exist;</button> <button>&part;</button> <button>&nabla;</button> <button>&prod;</button> <button>&sum;</button> <button>&plusmn;</button> <button>&radic;</button> <button>&infin;</button> <button>&int;</button> <button>&prop;</button> <button>&sim;</button> <button>&cong;</button> <button>&asymp;</button> <button>&ne;</button> <button>&equiv;</button> <button>&le;</button> <button>&ge;</button> <button>&sub;</button> <button>&sup;</button> <button>&nsub;</button> <button>&sube;</button> <button>&supe;</button> <button>&isin;</button> <button>&notin;</button> <button>&ni;</button> <button>&oplus;</button> <button>&otimes;</button> <button>&sdot;</button> <button>&and;</button> <button>&or;</button> <button>&cap;</button> <button>&cup;</button> <button>&real;</button> <button>&image;</button> <button>&empty;</button> <button>&deg;</button> <button>&prime;</button> <button>&micro;</button> <button>&larr;</button> <button>&uarr;</button> <button>&rarr;</button> <button>&darr;</button> <button>&harr;</button> <button>&lArr;</button> <button>&uArr;</button> <button>&rArr;</button> <button>&dArr;</button> <button>&hArr;</button>",true);$("#fenetre button").on("click",function(){insert(el,"","",$(this).text());$("#fenetre,#fenetre_fond").remove()})}function insertion_ol(el){popup('<a class="icon-ok" title="Valider"></a><h3>Insertion d\'une liste numérotée</h3>  <p>Choisissez le type de numérotation et la valeur de départ de la liste ci-dessous. Vous pouvez éventuellement modifier les différents éléments en les écrivant ligne par ligne. Vous pourrez ajouter un élément ultérieurement en l\'encadrant par les balises &lt;li&gt; et &lt;/li&gt;.</p>  <p class="ligne"><label for="t1">Numérotation numérique (1, 2, 3...)</label><input type="radio" name="type" id="t1" value="1" checked></p>  <p class="ligne"><label for="t2">Numérotation alphabétique majuscule (A, B, C...)</label><input type="radio" name="type" id="t2" value="A"></p>  <p class="ligne"><label for="t3">Numérotation alphabétique minuscule (a, b, c...)</label><input type="radio" name="type" id="t3" value="a"></p>  <p class="ligne"><label for="t4">Numérotation romaine majuscule (I, II, III...)</label><input type="radio" name="type" id="t4" value="I"></p>  <p class="ligne"><label for="t5">Numérotation romaine minuscule (i, ii, iii...)</label><input type="radio" name="type" id="t5" value="i"></p>  <p class="ligne"><label for="debut">Valeur de début (numérique)</label><input type="text" id="debut" value="1"></p>  <p class="ligne"><label for="lignes">Textes (chaque ligne correspond à un élément de la liste)&nbsp;: </label></p>  <textarea id="lignes" rows="5">'+marqueselection(el)+'</textarea>  <hr><h3>Aperçu</h3><div id="apercu"></div>',true);$("#fenetre :input").on("click keyup",function(){var debut=$("#debut").val();debut=debut.length&&debut>1?' start="'+debut+'"':"";$("#apercu").html('<ol type="'+$("[name='type']:checked").val()+'"'+debut+"><li>"+($("#lignes").val().length?$("#lignes").val().trim("\n").replace(/\n/g,"</li><li>"):"Première ligne</li><li>Deuxième ligne</li><li>...")+"</li></ol>")}).first().keyup();$("#lignes").focus();$("#fenetre a.icon-ok").on("click",function(){var debut=$("#debut").val();debut=debut.length&&debut>1?' start="'+debut+'"':"";var elements=$("#lignes").val().trim("\n");var index=elements.lastIndexOf("\n");if(index>0){var dernier=elements.substring(index+1);elements=elements.substring(0,index)}else var dernier="";insert(el,'<ol type="'+$("[name='type']:checked").val()+'"'+debut+"><li>"+elements.replace(/\n/g,"</li><li>")+"</li><li>","</li></ol>",dernier);$("#fenetre,#fenetre_fond").remove()});$("#fenetre a.icon-ferme,#fenetre_fond").on("click",function(){marqueselection(el,true)})}function insertion_ul(el){popup('<a class="icon-ok" title="Valider"></a><h3>Insertion d\'une liste à puces</h3>  <p>Vous pouvez éventuellement modifier les différents éléments en les écrivant ligne par ligne (chaque ligne correspond à un élément de la la liste). Vous pourrez ajouter un élément ultérieurement en l\'encadrant par les balises &lt;li&gt; et &lt;/li&gt;.</p>  <textarea id="lignes" rows="5">'+marqueselection(el)+'</textarea>  <hr><h3>Aperçu</h3><div id="apercu"></div>',true);$("#lignes").on("click keyup",function(){$("#apercu").html("<ul><li>"+($("#lignes").val().length?$("#lignes").val().trim("\n").replace(/\n/g,"</li><li>"):"Première ligne</li><li>Deuxième ligne</li><li>...")+"</li></ul>")}).keyup().focus();$("#fenetre a.icon-ok").on("click",function(){var elements=$("#lignes").val().trim("\n");var index=elements.lastIndexOf("\n");if(index>0){var dernier=elements.substring(index+1);elements=elements.substring(0,index)}else var dernier="";insert(el,"<ul><li>"+elements.replace(/\n/g,"</li><li>")+"</li><li>","</li></ul>",dernier);$("#fenetre,#fenetre_fond").remove()});$("#fenetre a.icon-ferme,#fenetre_fond").on("click",function(){marqueselection(el,true)})}function insertion_lien1(el){var sel=marqueselection(el);popup('<a class="icon-ok" title="Valider"></a><h3>Insertion d\'un lien vers un document de Cahier de Prépa</h3>  <div><p style="text-align:center; margin: 2em 0;">[Récupération des listes de documents]</p></div>  <div style="display:none;"><hr><h3>Aperçu</h3><div id="apercu" style="text-align:center;">[Veuillez choisir un document]</div></div>',true);$("#fenetre a.icon-ferme,#fenetre_fond").on("click",function(){marqueselection(el,true)});$.ajax({url:"recup.php",method:"post",data:{action:"docs"},dataType:"json"}).done(function(data){var majapercu=function(){var apercu=$("#apercu");var id=$("#doc").val();var texte=$("#doc option:selected").text();if(id==0)apercu.html(texte);else if($("#vue").is(":checked")){var l=$("#largeur").val();if(texte.slice(-4,-1)=="pdf"){if(apercu.children(".pdf").length==0)apercu.html('<div><object data="download?id='+id+'" type="application/pdf" height="100%" width="100%"> <a href="download?id='+id+'">'+texte+"</a> </object></div>");else if(apercu.find("object").attr("data").substr(12)!=id)apercu.find("object").attr("data","download?id="+id).html('<a href="download?id='+id+'">'+texte+"</a>");apercu.children().attr("class","pdf "+$("#format").val());if(l){if(l==100)apercu.children().removeAttr("style").children().attr("width","100%").removeAttr("style");else{apercu.children().css("padding-bottom",$('<div class="'+$("#format").val()+'"></div>').css("padding-bottom").slice(0,-1)*l/100+"%");apercu.find("object").attr("width",l+"%").css("left",(100-l)/2+"%")}}}else if("jpgpegpng".indexOf(texte.slice(-4,-1))>-1){if(apercu.children("img").length==0)apercu.css("text-align","").html('<img src="download?id='+id+'">');else if(apercu.children().attr("src").substr(12)!=id)apercu.children().attr("src","download?id="+id);if(l){if(l==100)apercu.children().removeAttr("style");else apercu.children().css("width",l+"%").css("margin-left",(100-l)/2+"%")}}}else $("#apercu").css("text-align","center").html('<a onclick="return false;" href="download?id='+this.value+'">'+$("#texte").val()+"</a>")};var affichedocs=function(data){$("#fenetre > div:first").html('  <p>Choisissez ci-dessous le répertoire puis le document à insérer. Vous pouvez aussi modifier le texte visible. Cela reste modifiable ultérieurement&nbsp;: le texte est situé entre les deux balises &lt;a...&gt; et &lt;/a&gt;.</p>  <p class="ligne"><label for="mat">Matière&nbsp;:</label><select id="mat">'+data.mats+'</select></p>  <p class="ligne"><label for="rep">Répertoire&nbsp;:</label><select id="rep"></select></p>  <p class="ligne"><label for="doc">Document&nbsp;:</label><select id="doc"></select></p>  <p class="ligne"><label for="texte">Texte visible&nbsp;:</label><input type="text" id="texte" value="'+sel+'" size="80" data-auto="1"></p>  <p class="ligne"><label for="vue">Afficher dans la page (PDF et image uniquement)</label><input type="checkbox" id="vue">  <p class="ligne"><label for="largeur">Largeur en %&nbsp;:</label><input type="text" id="largeur" value="100" size="3"></p>  <p class="ligne"><label for="format">Format (PDF uniquement)</label><select id="format">    <option value="portrait">A4 vertical</option><option value="paysage">A4 horizontal</option><option value="hauteur50">Hauteur 50%</option>  </select>');$("#fenetre > div:last").show();if($("#texte").val().length)$("#texte").attr("data-auto",0);$("#doc").on("change keyup",function(e){if(e.which==13)$("#fenetre a.icon-ok").click();var texte=$("#doc option:selected").text();if($("#texte").attr("data-auto")==1)$("#texte").val(this.value>0?texte.substr(0,texte.lastIndexOf("(")-1):"---");if("pdfjpgpegpng".indexOf(texte.slice(-4,-1))>-1)$("#vue").change().parent().show();else{$("#vue, #largeur, #format").parent().hide();$("#vue").prop("checked",false)}majapercu()});$("#texte").on("change keypress",function(e){if(e.which==0)return;if(e.which==13)$("#fenetre a.icon-ok").click();if(this.value.length==0){$(this).data("auto",1);$("#doc").change()}else{$(this).data("auto",0);majapercu()}});$("#vue").on("change",function(){if($("#vue").is(":checked")){if($("#doc option:selected").text().slice(-4,-1)=="pdf"){$("#largeur, #format").parent().show();$("#texte").parent().hide()}else if("jpgpegpng".indexOf($("#doc option:selected").text().slice(-4,-1))>-1){$("#largeur").parent().show();$("#format, #texte").parent().hide()}}else{$("#texte").parent().show();$("#largeur, #format").parent().hide()}majapercu()});$("#format").on("change keyup",function(e){if(e.which==13)$("#fenetre a.icon-ok").click();majapercu()});$("#largeur").on("keydown",function(e){if(e.which==38)++this.value;else if(e.which==40)--this.value}).on("change keyup",function(e){if(e.which==0)return;if(e.which==13)$("#fenetre a.icon-ok").click();if(this.value!=$(this).data("valeur")){$(this).data("valeur",this.value);majapercu()}}).attr("data-valeur",100);$("#rep").on("change",function(){$("#doc").html(data.docs[this.value]).change()});$("#mat").on("change",function(){$("#rep").html(data.reps[this.value]).change()}).focus().change();$("#fenetre a.icon-ok").on("click",function(){if($("#doc").val()){if($("#vue").is(":checked")&&"pdfjpgpegpng".indexOf($("#doc option:selected").text().slice(-4,-1))>-1)insert(el,$("#apercu").html(),"","");else insert(el,'<a href="download?id='+$("#doc").val()+'">',"</a>",$("#texte").val());$("#fenetre,#fenetre_fond").remove()}});$("#mat option").each(function(){if($("body").attr("data-matiere")==this.value)$("#mat").val(this.value).change()})};if("mats"in data)affichedocs(data)})}function insertion_lien2(el){popup('<a class="icon-ok" title="Valider"></a><h3>Insertion d\'un lien</h3>  <p class="ligne"><label for="texte">Texte visible&nbsp;: </label><input type="text" id="texte" value="'+marqueselection(el)+'" size="80"></p>  <p class="ligne"><label for="url">Adresse&nbsp;: </label><input type="text" id="url" value="http://" size="80"></p>  <hr><h3>Aperçu</h3><div id="apercu" style="text-align:center;"></div>',true);$("#fenetre input").on("click keyup",function(){$("#apercu").html($("#texte").val().length?'<a onclick="return false;" href="'+$("#url").val()+'">'+$("#texte").val()+"</a>":"[Écrivez un texte visible]")}).on("keypress",function(e){if(e.which==13)$("#fenetre a.icon-ok").click()}).first().keyup().focus();$("#fenetre a.icon-ok").on("click",function(){insert(el,'<a href="'+$("#url").val()+'">',"</a>",$("#texte").val());$("#fenetre,#fenetre_fond").remove()});$("#fenetre a.icon-ferme,#fenetre_fond").on("click",function(){marqueselection(el,true)})}function insertion_tex(el){var chargement=typeof MathJax=="undefined"?'<script type="text/javascript" src="/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script><script type="text/x-mathjax-config">MathJax.Hub.Config({tex2jax:{inlineMath:[["$","$"],["\\\\(","\\\\)"]]}});</script>':"";var sel=marqueselection(el);var type="t1";if(sel.length)switch(sel.substring(0,2)){case"\\[":case"$$":type="t2";case"\\(":sel=sel.substring(2,sel.length-2);break;default:sel=sel.trim("$")}popup(chargement+'<a class="icon-montre" title="Mettre à jour l\'aperçu"></a><a class="icon-ok" title="Valider"></a><h3>Insertion de formules LaTeX</h3>  <p>Vous pouvez ci-dessous entrer et modifier une formule LaTeX. L\'aperçu présent en bas sera mis à jour uniquement lorsque vous cliquez sur l\'icône <span class="icon-montre"></span>.</p>  <p class="ligne"><label for="t1">La formule est en ligne (pas de retour)</label><input type="radio" name="type" id="t1" value="1"></p>  <p class="ligne"><label for="t2">La formule est hors ligne (formule centrée)</label><input type="radio" name="type" id="t2" value="2"></p>  <textarea id="formule" rows="3">'+sel+'</textarea>  <hr><h3>Aperçu</h3><div id="apercu" style="text-align:center;">[Demandez l\'aperçu en cliquant sur l\'icône <span class="icon-montre"></span>]</div>',true);$("#"+type).prop("checked",true);$("#formule").focus();$("#fenetre a.icon-montre").on("click",function(){if($("#formule").val().length){$("#apercu").html($("#t1").is(":checked")?"$"+$("#formule").val()+"$":"\\["+$("#formule").val()+"\\]").css("text-align","left");MathJax.Hub.Queue(["Typeset",MathJax.Hub,"apercu"])}else $("#apercu").html("[Écrivez une formule]").css("text-align","center")});$("#fenetre a.icon-ok").on("click",function(){if($("#t1").is(":checked"))insert(el,"$","$",$("#formule").val());else insert(el,"\\[","\\]",$("#formule").val());$("#fenetre,#fenetre_fond").remove()});$("#fenetre a.icon-ferme,#fenetre_fond").on("click",function(){marqueselection(el,true)})}function insertion_par1(el){insert(el,"<p>","</p>")}function insertion_par2(el){insert(el,"<div class='note'>","</div>")}function insertion_par3(el){insert(el,"<div class='annonce'>","</div>")}function insertion_retour(el){insert(el,"<br>","")}function insertion_gras(el){insert(el,"<strong>","</strong>")}function insertion_italique(el){insert(el,"<em>","</em>")}function insertion_souligne(el){insert(el,"<u>","</u>")}function insertion_exp(el){insert(el,"<sup>","</sup>")}function insertion_ind(el){insert(el,"<sub>","</sub>")}function aidetexte(){popup('<h3>Aide et explications</h3>  <p>Il y a deux modes d\'éditions possibles pour éditer un texte&nbsp;: le mode «&nbsp;balises visibles&nbsp;» et le mode «&nbsp;balises invisibles&nbsp;». Il est possible de passer de l\'un à l\'autre&nbsp;:</p>  <ul>    <li><span class="icon-source"></span> permet de passer en mode «&nbsp;balises visibles&nbsp;» (par défaut), où le texte à taper est le code HTML de l\'article. Ce mode est plus précis. Les boutons aux dessus aident à utiliser les bonnes balises.</li>    <li><span class="icon-nosource"></span> permet de passer en mode «&nbsp;balises invisibles&nbsp;», où le texte est tel qu\'il sera affiché sur la partie publique, et modifiable. Ce mode est moins précis, mais permet le copié-collé depuis une page web ou un document Word/LibreOffice.  </ul>  <p>Une fonction de nettoyage du code HTML, permettant d\'assurer une homogénéité et une qualité d\'affichage optimales, est lancée à chaque commutation entre les deux modes, à chaque clic sur un des boutons disponibles, à chaque copie/coupe de texte et à chaque passage à la ligne.</p>  <p>En HTML, toutes les mises en formes sont réalisées par un encadrement de texte entre deux balises&nbsp;: &lt;h3&gt; et &lt;/h3&gt; pour un gros titre, &lt;p&gt; et &lt;/p&gt; pour un paragraphe. Le retour à la ligne simple, qui ne doit exister que très rarement, est une balise simple &lt;br&gt;. Mais les boutons disponibles sont là pour vous permettre de réaliser le formattage que vous souhaitez&nbsp;:</p>  <ul>    <li><span class="icon-titres"></span>&nbsp;: différentes tailles de titres (fenêtre supplémentaire pour choisir)</li>    <li><span class="icon-par1"></span>&nbsp;: paragraphe classique, qui doit obligatoirement encadrer au minimum chaque ligne de texte. Apparaît automatiquement au passage à la ligne si on l\'oublie.</li>    <li><span class="icon-par2"></span>&nbsp;: paragraphe important, écrit en rouge</li>    <li><span class="icon-par3"></span>&nbsp;: paragraphe très important, écrit en rouge et encadré</li>    <li><span class="icon-retour"></span>&nbsp;: retour à la ligne. Identique à un appui sur Entrée, et souvent inutile.</li>    <li><span class="icon-gras"></span>&nbsp;: mise en gras du texte entre les balises</li>    <li><span class="icon-italique"></span>&nbsp;: mise en italique du texte entre les balises</li>    <li><span class="icon-souligne"></span>&nbsp;: soulignement du texte entre les balises</li>    <li><span class="icon-omega"></span>&nbsp;: lettres grecques (fenêtre supplémentaire pour choisir)</li>    <li><span class="icon-sigma"></span>&nbsp;: symboles mathématiques (fenêtre supplémentaire pour choisir)</li>    <li><span class="icon-exp"></span>&nbsp;: mise en exposant du texte entre les balises</li>    <li><span class="icon-ind"></span>&nbsp;: mise en indice du texte entre les balises</li>    <li><span class="icon-ol"></span>&nbsp;: liste numérotée. Une fenêtre supplémentaire permet de choisir le type (1,A,a,I,i) et la première valeur. Les différentes lignes de la liste sont constituées par les balises &lt;li&gt; et &lt;/li&gt;</li>    <li><span class="icon-ul"></span>&nbsp;: liste à puces. Les différentes lignes de la liste sont constituées par les balises &lt;li&gt; et &lt;/li&gt;</li>    <li><span class="icon-lien1"></span>&nbsp;: lien d\'un document disponible ici (fenêtre supplémentaire pour choisir)</li>    <li><span class="icon-lien2"></span>&nbsp;: lien vers un autre site web (fenêtre supplémentaire pour entre l\'adresse)</li>    <li><span class="icon-tex"></span>&nbsp;: insertion de code LaTeX (fenêtre supplémentaire pour le taper)</li>  </ul>  <p class="tex2jax_ignore">Il est possible d\'insérer du code en LaTeX, sur une ligne séparée (balises \\[...\\] ou balises $$...$$) ou au sein d\'une phrase (balises $...$ ou balises \\(...\\)). Il faut ensuite taper du code en LaTeX à l\'intérieur. La prévisualisation est réalisée en direct.</p>',false)
-}function echange(el1,el2){if(el1.length&&el2.length){$("article").css("position","relative");el1.css("opacity",.3);el2.css("opacity",.3);el2.animate({top:el1.position().top-el2.position().top},1e3);el1.animate({top:(el2.outerHeight(true)+el2.outerHeight())/2},1e3,function(){el1.css("opacity",1);el2.css("opacity",1);el1.insertAfter(el2);el1.css({position:"static",top:0});el2.css({position:"static",top:0})})}}function cache(el){var prop=el.parent().attr("data-id").split("|");$.ajax({url:"ajax.php",method:"post",data:{cache:1,action:prop[0],id:prop[1]},dataType:"json",el:el,fonction:function(el){el.parent().addClass("cache");el.removeClass("icon-cache").addClass("icon-montre").off("click").on("click",function(){montre($(this))}).attr("title","Montrer à nouveau")}})}function montre(el){var prop=el.parent().attr("data-id").split("|");$.ajax({url:"ajax.php",method:"post",data:{montre:1,action:prop[0],id:prop[1]},dataType:"json",el:el,fonction:function(el){el.parent().removeClass("cache");el.removeClass("icon-montre").addClass("icon-cache").off("click").on("click",function(){cache($(this))}).attr("title","Cacher à nouveau")}})}function monte(el){var parent=el.parent();var prop=parent.attr("data-id").split("|");$.ajax({url:"ajax.php",method:"post",data:{monte:1,action:prop[0],id:prop[1]},dataType:"json",el:parent,fonction:function(el){if(!el.prev().prev().is("article")){el.children(".icon-monte").hide(1e3);el.prev().children(".icon-monte").show(1e3)}if(!el.next().is("article")){el.children(".icon-descend").show(1e3);el.prev().children(".icon-descend").hide(1e3)}echange(el.prev(),el)}})}function descend(el){var parent=el.parent();var prop=parent.attr("data-id").split("|");$.ajax({url:"ajax.php",method:"post",data:{descend:1,action:prop[0],id:prop[1]},dataType:"json",el:parent,fonction:function(el){if(!el.prev().is("article")){el.children(".icon-monte").show(1e3);el.next().children(".icon-monte").hide(1e3)}if(!el.next().next().is("article")){el.children(".icon-descend").hide(1e3);el.next().children(".icon-descend").show(1e3)}echange(el,el.next())}})}function supprime(el){var parent=el.parent();var prop=parent.data("id").split("|");var item="un élément";switch(prop[0]){case"infos":item="une information";break;case"pages":item="la matière <em>"+$("h3",parent).text()+"</em>. Les informations qui y sont écrites seront aussi supprimées";break;case"reps":item="le répertoire <em>"+$(".nom",parent).map(function(){return this.textContent||$(this).find("input").val()}).get(0)+"</em>. Tous les sous-répertoires et documents qui s'y trouvent seront aussi supprimés";break;case"docs":item="le document <em>"+$(".nom",parent).map(function(){return this.textContent||$(this).find("input").val()}).get(0)+"</em>";break;case"colles":item="le programme de colle de la "+$(".edition",parent).text().toLowerCase();break;case"cdt-elems":item="un élément du cahier de texte";break;case"cdt-types":item="le type de séances <em>"+$("h3",parent).text()+"</em>. Les éléments du cahier de texte associés à ce type seront aussi supprimés";break;case"cdt-raccourcis":item="le raccourci de séance <em>"+$("h3",parent).text()+"</em>. Aucun élément du cahier de texte ne sera supprimé";break;case"notes":parent=parent.parent();item="une colle du <em>"+$("td:first",parent).text()+"</em>, d'une durée de "+$("td:eq(3)",parent).text()+". Toutes les notes associées seront supprimées";break;case"matieres":item="la matière <em>"+$("h3",parent).text()+"</em>. Les programmes de colles, le cahier de texte et les notes correspondantes seront supprimées. Les répertoires, les documents, les pages d'informations spécifiques et les éléments de l'agenda associés à la matière seront conservés mais ne seront plus associés à une matières, donc visibles dans le contexte «&nbsp;général&nbsp;»";break;case"groupes":item="le groupe <em>"+($(".editable",parent).text()||$("input:first",parent).val())+"</em>. Les utilisateurs concernés ne seront pas supprimés";break;case"agenda-elems":item="un événement de l'agenda";break;case"agenda-types":item="le type d'événement <em>"+$("h3",parent).text()+"</em>. Les événements de l'agenda associés à ce type seront aussi supprimés";break}confirmation("Vous allez supprimer XXX.<br>Cette opération n'est pas annulable.".replace("XXX",item),this,function(el){$.ajax({url:"ajax.php",method:"post",data:{supprime:1,action:prop[0],id:prop[1]},dataType:"json",el:parent,fonction:function(el){if(prop[0].match(/^(agenda|colles)$/))location.reload(true);else el.remove()}})})}function lock(el){var parent=el.parent();var prop=parent.data("id").split("|");var protection=el.data("val");popup('<a class="icon-ok" title="Valider ce choix"></a><h3>Accès à l\'information</h3><table id="selmult">  <tr class="categorie"><td>Accès public</td><td><input value="0" type="checkbox"></td></tr>  <tr class="categorie"><td>Utilisateurs identifiés</td><td><input value="6" type="checkbox"></td></tr>  <tr class="element"><td>Invités</td><td><input value="1" type="checkbox"></td></tr>  <tr class="element"><td>Élèves</td><td><input value="2" type="checkbox"></td></tr>  <tr class="element"><td>Colleurs</td><td><input value="3" type="checkbox"></td></tr>  <tr class="element"><td>Administratifs</td><td><input value="4" type="checkbox"></td></tr>  <tr class="element"><td>Professeurs</td><td><input value="5" type="checkbox"></td></tr>  <tr class="categorie"><td>Information invisible</td><td><input value="32" type="checkbox"></td></tr>  </tbody></table>',true);var f=$("#fenetre");if(protection==0||protection==32)$('input[value="'+protection+'"]',f).prop("checked",true).change();else{$("input[value=6]",f).prop("checked",true).change();for(var a=1;a<6;a++)if((protection-1>>a-1&1)==0)$('input[value="'+a+'"]',f).prop("checked",true).change()}var f=$("#fenetre");$("input[value=0],input[value=6],input[value=32]",f).parent().parent().addClass("categorie");$("tr:not(.categorie)",f).addClass("element");$("input",f).on("click",function(){if(this.value==0||this.value==32)$(this).parent().parent().siblings().find("input[type=checkbox]").prop("checked",false).change();else{$("input[value=0],input[value=32]",f).prop("checked",false).change();$("input[value=6]",f).prop("checked",true).change();if(this.value==6)$("tr:not(.categorie) input",f).prop("checked",true).change()}});$("tr",f).on("click",function(e){if(!$(e.target).is("input"))$(this).find("input").click()});$("input",f).on("change",function(){$(this).parent().parent().removeClass("sel");if(this.checked)$(this).parent().parent().addClass("sel")});$(".icon-ok",f).on("click",function(){if($('input[value="32"]',f).prop("checked"))var val=32;else if($('input[value="0"]',f).prop("checked"))var val=0;else var val=32-$("input:checked:not([value=6])",f).map(function(){return this.value|0}).get().reduce(function(acc,v){return acc+Math.pow(2,v-1)},0);el.data("val",val);$.ajax({url:"ajax.php",method:"post",data:{action:prop[0],id:prop[1],champ:"protection",val:val},dataType:"json",el:parent,fonction:function(el){location.reload(true)}})})}function ajoutecolle(el){var article=el.parent();el.before('<a class="icon-annule" title="Annuler"></a><a class="icon-ok" title="Valider"></a>');el.next().addBack().hide();var form=$("<form></form>").appendTo(article).html($("#form-ajoutecolle").html());$("textarea",form).textareahtml();$("input",form).attr("id","cache");$(".icon-annule",article).on("click",function(){$("form,.icon-annule,.icon-ok",article).remove();el.next().addBack().show()});$("a.icon-ok",article).on("click",function(){$("textarea",form).each(function(){this.value=nettoie($(this).is(":visible")?this.value:$(this).next().html())});var id=article.data("id").split("|")[1];$.ajax({url:"ajax.php",method:"post",data:form.serialize()+"&action=ajout-colle&id="+id,dataType:"json",el:article,fonction:function(el){var texte=$("textarea",el).val();var cache=$("input",el).is(":checked");if(cache)el.addClass("cache");el.data("id","colles|"+id);$(".icon-aide",el).nextAll().remove();$(".icon-aide",el).after((cache?'<a class="icon-montre" title="Afficher le programme de colles sur la partie publique"></a>':'<a class="icon-cache" title="Rendre invisible le programme de colles sur la partie publique"></a>')+'<a class="icon-supprime" title="Supprimer ce programme de colles"></a><div class="editable edithtml" data-id="colles|texte|'+id+'" placeholder="Texte du programme de colles">'+texte+"</div>");$("a.icon-cache,a.icon-montre,a.icon-supprime",el).on("click",function(){window[this.className.substring(5)]($(this))});$(".editable",el).editinplace()}})});$("input,select",form).on("keypress",function(e){if(e.which==13){e.preventDefault();$("a.icon-ok",article).click()}})}function valide(){var data="";if($("#planning").length)data="action=planning&"+$("form").serialize();else{var id=$(this).parent().attr("data-id").split("|");data="action="+id[0]+"&id="+id[1]+"&"+$(this).nextAll("form").serialize()}if(data.length)$.ajax({url:"ajax.php",method:"post",data:data,dataType:"json",el:this,fonction:function(el){if(el.classList[1]!="noreload")location.reload(true)}});else affiche("<p>Aucune donnée envoyée.</p>","nok")}function formulaire(){var idform=this.className.split(" ")[0].substring(5);var action=$("#form-"+idform).data("action");$("#epingle").remove();var article=$('<article id="epingle"><a class="icon-ferme" title="Fermer"></a>  <a class="icon-aide" title="Aide pour ce formulaire"></a>  <a class="icon-ok" title="Valider"></a></article>').insertBefore($("article,#calendrier,#parentsdoc+*").first());var form=$("<form></form>").appendTo(article).html($("#form-"+idform).html());$(".edithtml",form).textareahtml();$("input[name], select[name]:not([multiple])",form).attr("id",function(){return this.getAttribute("name")});switch(action){case"reps":$(this).init_reps();break;case"ajout-rep":form.append('<input type="hidden" name="parent" value="'+$(this).parent().data("id").split("|")[1]+'">');break;case"docs":case"ajout-doc":$(this).init_docs(action);break;case"cdt-elems":form.init_cdt_boutons();break;case"ajout-cdt-raccourci":form.init_cdt_raccourcis();break;case"notes":case"ajout-notes":$(this).init_notes(action);break;case"agenda-elems":$(this).init_evenements();break;case"deplcolle":$("#ancien,#nouveau").each(function(){$(this).datetimepicker({format:"d/m/Y Ghi",timepicker:true})});break;case"ajout-utilisateurs":form.init_ajout_utilisateurs();break;case"ajout-groupe":$(".usergrp span",form).on("click",utilisateursgroupe);break}$("select[multiple]",form).each(selmult);$("#epingle .icon-ferme").on("click",function(){$("#epingle").remove()});$("#epingle a.icon-aide").on("click",function(){popup($("#aide-"+idform).html(),false)});$("#epingle a.icon-ok").on("click",function(){$(".edithtml",form).each(function(){this.value=nettoie($(this).is(":visible")?this.value:$(this).next().html())});if(action=="notes"||action=="ajoute-notes")$("#epingle select:not(:visible)").val("x");$.ajax({url:"ajax.php",method:"post",data:form.serialize()+"&action="+action,dataType:"json",el:"",fonction:function(el){location.reload(true)}})});$("input,select",form).on("keypress",function(e){if(e.which==13){e.preventDefault();$("#epingle a.icon-ok").click()}})}$.fn.init_reps=function(){var el=$(this);var form=$("#epingle form");var sel=$("select[multiple]",form);var id=el.parent().data("id").split("|")[1];var donnees=el.parent().data("donnees").split("|");var protection=donnees[2];var nom=el.siblings(".nom").text().split(/\/\s/).pop()||el.parent().find("input").val();$("em",form).text(nom);if(protection==0||protection==32)sel.val(protection);else{sel.val(6);for(var a=1;a<6;a++)if((protection-1>>a-1&1)==0)$('option[value="'+a+'"]',sel).prop("selected",true)}if(donnees[0]==0)$("#nom,#parent,#menu",form).parent().remove();else{$("#nom",form).val(nom);if(donnees[1]=="1")$("#menu",form).prop("checked",true);$('[data-parents*=",'+id+',"]',form).prop("disabled",true)}form.append('<input type="hidden" name="id" value="'+id+'">');$('input[type="button"]',form).on("click",function(){var action=this.value.substring(0,4)=="Prop"?"propage":"vide";var contexte=$(this).parent().find("em").text();var texte=action=="propage"?"Vous allez propager le réglage d'accès du répertoire <em>"+contexte+"</em> à l'ensemble de ses sous-répertoires et des documents qu'ils contiennent.<br>Vous pourrez modifier à nouveau le réglage de chaque document ou répertoire, de façon individuelle.":"Vous allez vider le répertoire <em>"+contexte+"</em>. Cela supprimera définitivement l'ensemble de ses sous-répertoires et des documents qu'ils contiennent.<br>Cette opération n'est pas annulable.";confirmation(texte,this,function(el){$.ajax({url:"ajax.php",method:"post",data:"action=reps&id="+id+"&"+action+"=1",dataType:"json",el:"",fonction:function(el){location.reload(true)}})})})};$.fn.init_docs=function(action){var el=$(this);var form=$("#epingle form");var nom=el.siblings(".nom").text().split(/\/\s/).pop()||el.parent().find("input").val();$("em",form).text(nom);var id=el.parent().data("id").split("|")[1];if(action=="docs"){var protection=el.parent().data("protection");form.append('<input type="hidden" name="id" value="'+id+'">');$("#nom",form).val(nom)}else{var protection=el.parent().data("donnees").split("|")[2];$("#fichier",form).on("change",function(){if(!$("#nom",form).val().length){var f=this.value;$("#nom",form).val(f.substring(f.lastIndexOf("\\")+1,f.lastIndexOf("."))||f)}});form.append('<input type="hidden" name="parent" value="'+id+'">')}var sel=$("select[multiple]",form);if(protection==0||protection==32)sel.val(protection);else{sel.val(6);for(var a=1;a<6;a++)if((protection-1>>a-1&1)==0)$('option[value="'+a+'"]',sel).prop("selected",true)}form.append('<input type="hidden" name="action" value="'+action+'">');$("#epingle a.icon-ok").addClass("icon-envoidoc").removeClass("icon-ok").on("click",function(){$.ajax({url:"docs.php",method:"post",data:"connexion=1",dataType:"json",el:"",fonction:function(el){window.clearTimeout(extinction);$("#log").html("Envoi du document. Cela peut prendre du temps...");var data=new FormData(form[0]);$.ajax({url:"ajax.php",method:"post",data:data,dataType:"json",contentType:false,processData:false,el:"",fonction:function(el){location.reload(true)}})}})})};$.fn.init_cdt_boutons=function(){var form=this;$("#jour,#pour").datetimepicker({format:"d/m/Y",timepicker:false});$("#h_debut").datetimepicker({format:"Ghi",datepicker:false,onClose:function(t,input){$("#h_fin").val(function(i,v){return v||(input.val().length?parseInt(input.val().slice(0,-3))+2+input.val().slice(-3):"")})}});$("#h_fin").datetimepicker({format:"Ghi",datepicker:false});var zero=function(n){return String(n).length==1?"0"+n:String(n)};$("#raccourci").on("change keyup",function(){var valeurs=raccourcis[this.value];for(var cle in valeurs){if(cle=="jour"){var t=new Date;var j=parseInt(valeurs["jour"]);t.setDate(j>t.getDay()?t.getDate()-t.getDay()-7+j:t.getDate()-t.getDay()+j);$("#jour").val(zero(t.getDate())+"/"+zero(t.getMonth()+1)+"/"+t.getFullYear())}else $("#"+cle).val(valeurs[cle])}$(this).data("modif",1);$("#tid").change()}).data("modif",0);$("#tid").on("change keyup",function(){switch(parseInt(seances[this.value])){case 0:$("#h_debut,#demigroupe").parent().show();$("#h_fin,#pour").parent().hide();break;case 1:$("#h_debut,#h_fin,#demigroupe").parent().show();$("#pour").parent().hide();break;case 2:$("#h_debut,#h_fin").parent().hide();$("#pour,#demigroupe").parent().show();break;case 3:$("#h_debut,#h_fin,#pour").parent().hide();$("#demigroupe").parent().show();break;default:$("#h_debut,#h_fin,#pour,#demigroupe").parent().hide()}$("#jour").change()});$("input,#demigroupe",form).on("change keyup",function(){if($("#raccourci").data("modif")==0)$("#raccourci").val(0);else $("#raccourci").data("modif",0)});$("input,select",form).on("keypress",function(e){if(e.which==13)$("a.icon-ok",el).click()});$("select:first",form).focus();$("#tid").change()};$.fn.init_cdt_raccourcis=function(){this.each(function(){var form=$(this);$('[id^="h_d"]',form).datetimepicker({format:"Ghi",datepicker:false,onClose:function(t,input){$('[id^="h_f"]',form).val(function(i,v){return v||(input.val().length?parseInt(input.val().slice(0,-3))+2+input.val().slice(-3):"")})}});$('[id^="h_fin"]').datetimepicker({format:"Ghi",datepicker:false});$('[id^="type"]',form).on("change keyup",function(){switch(parseInt(seances[this.value])){case 0:$('[id^="h_d"],[id^="dem"]',form).parent().show();$('[id^="h_f"]',form).parent().hide();break;case 1:$('[id^="h_d"],[id^="h_f"],[id^="dem"]',form).parent().show();break;case 2:case 3:$('[id^="h_d"],[id^="h_f"]',form).parent().hide();$('[id^="dem"]',form).parent().show();break;default:$('[id^="h_d"],[id^="h_f"],[id^="dem"]',form).parent().hide()}}).change();$("input,select",form).on("keypress",function(e){if(e.which==13)$("a.icon-ok",form).click()})})};$.fn.init_notes=function(action){var el=$(this);var form=$("#epingle form").append($("#form-notes").html());$("input, select",form).attr("id",function(){return this.getAttribute("name")});$("tr[data-id]",form).append("<td>"+$("div",form).html()+"</td>");$("table select",form).attr("name",function(){return"e"+$(this).parent().parent().data("id")});$("div",form).remove();if($("input:checkbox",form).length){$("tr[data-id]",form).hide();$("input:checkbox",form).on("click",function(){if($("input:checkbox:last",form).prop("checked"))return $("tr[data-id]",form).show();var ids=$("input:checked",form).map(function(){return this.value.split(",")}).get().concat();$("tr[data-id]:not(.orig)",form).hide();for(var i=0;i<ids.length;i++)$('tr[data-id="'+ids[i]+'"]',form).show()})}function marque_dejanotes(sid){if(sid==0)return true;var dn=dejanotesautres[sid].split(",");for(var i=0;i<dn.length;i++)$('tr[data-id="'+dn[i]+'"]',form).addClass("dejanote").find("td:eq(0)").text(function(){return this.textContent+" (noté par un autre colleur)"});var dn=dejanotesperso[sid].split(",");for(var i=0;i<dn.length;i++)$('tr[data-id="'+dn[i]+'"]:not(.orig)',form).addClass("dejanote").find("td:eq(0)").text(function(){return this.textContent+" (déjà noté par vous-même)"});$(".dejanote select").prop("disabled",true).val("x")}$("#jour").datetimepicker({format:"d/m/Y",timepicker:false,onShow:function(){this.setOptions({minDate:debut||$("#sid option:selected").data("date"),maxDate:new Date(new Date((fin||$("#sid option:selected").next().data("date")).replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z){return z+"-"+y+"-"+x})).getTime()-864e5)})}});$("#heure").datetimepicker({format:"Ghi",datepicker:false,defaultTime:"15h30"});$("#duree").datetimepicker({format:"Ghi",datepicker:false,defaultTime:"0h00",step:10}).on("change",function(){$(this).removeClass("auto")});$("#sid").on("change keyup",function(){$(".dejanote td:first-child").text(function(){return this.textContent.replace(" (noté par un autre colleur)","").replace(" (déjà noté par vous-même)","")});$(".dejanote").removeClass("dejanote").find("select").prop("disabled",false);marque_dejanotes($("#sid").val());var jour=new Date($("#jour").val().replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z){return z+"-"+y+"-"+x}));var debut=new Date($("#sid option:selected").data("date").replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z){return z+"-"+y+"-"+x}));var fin=new Date($("#sid option:selected").next().data("date").replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z){return z+"-"+y+"-"+x}));if(jour<debut||jour>fin){debut=debut.toJSON();$("#jour").val(debut.substr(8,2)+"/"+debut.substr(5,2)+"/"+debut.substr(0,4))}}).change();$("select",form).on("change keyup",function(){var nb=$("table select:visible",form).filter(function(){return this.value!="x"}).length;var duree=nb*(dureecolle||20);if($("#duree").is(".auto")||duree>$("#duree").val().replace(/^(\d*)h(\d*)$/,function(tout,x,y){return 60*(x|0)+(y|0)}))$("#duree").val((duree/60|0)+"h"+(duree%60||"")).addClass("auto")});if(action=="notes"){var tr=el.parent().parent();var sid=el.data("sid");var debut=$('select[name="sid"] option[value="'+sid+'"]').data("date");var fin=$('select[name="sid"] option[value="'+sid+'"]').next().data("date");var eleves=el.data("eleves").split("|");var notes=el.data("notes").split("|");for(var i=0;i<eleves.length;i++)$('tr[data-id="'+eleves[i]+'"]',form).addClass("orig").show().find("select").val(notes[i]).on("change",function(){$(this).parent().parent().removeClass("orig")});$("h3",form).text("Modifier des notes - semaine du "+$('select[name="sid"] option[value="'+sid+'"]').text().split(" ").slice(0,3).join(" "));$("#id").val(el.parent().data("id").split("|")[1]);$("#jour").val($("td:eq(0)",tr).text().replace(/(.{6})(.{2})/,function(tout,x,y){return x+"20"+y}));$("#heure").val($("td:eq(1)",tr).text().replace("-",""));$("#duree").val($("td:eq(3)",tr).text());if(el.next().length){marque_dejanotes(sid)}else{$("tr:not(.orig)",form).hide();$('.orig option[value="x"]',form).remove();$("#duree").prop("disabled",true);form.append("<p>Cette colle a déjà été relevée&nbsp;: il est impossible de modifier quels élèves ont été interrogés ou la durée de la colle. Vous pouvez corriger la date et l'heure (dans la limite de la semaine enregistrée) ou les notes que vous avez mises vous pouvez mettre une note à un élève initialement absent qui a rattrapé sa colle.</p>")}}};$.fn.init_ajout_utilisateurs=function(){$("#autorisation,#saisie").on("change",function(){var f=$("#epingle form");var a=$("#autorisation",f).val();if(a==0){$(".affichesiinvite,.affichesiinvitation,.affichesimotdepasse,.mailenvoi,.mailliste",f).hide(0);$("textarea",f).prop("disabled",true).attr("placeholder","Zone de saisie des utilisateurs\nSélectionnez d'abord un type d'utilisateur")}else{var inv=a==1;var mdp=$("#saisie",f).val()==2;$("#saisie",f).parent().toggle(!inv);$(".affichesiinvite",f).toggle(inv);$(".affichesiinvitation",f).toggle(!inv&&!mdp);$(".affichesimotdepasse",f).toggle(!inv&&mdp);$(".mailenvoi",f).toggle(!inv);$(".mailliste",f).toggle(a>2);$("#mailenvoi",f).prop("disabled",mdp).change();$("textarea",f).prop("disabled",false).attr("placeholder",function(){if(inv)return"identifiant_1,motdepasse_1\nidentifiant_2,motdepasse_2\nidentifiant_3,motdepasse_3\n...";else if(mdp)return"nom_1,prénom_1,motdepasse_1\nnom_2,prénom_2,motdepasse_2\nnom_3,prénom_3,motdepasse_3\n...";else return"nom_1,prénom_1,adresse_1\nnom_2,prénom_2,adresse_2\nnom_3,prénom_3,adresse_3\n..."})}}).change();$("#epingle #mailenvoi").on("change",function(){$("#epingle #mailliste").attr("disabled",!this.checked||this.disabled)}).change()};$.fn.init_evenements=function(){var el=$(this);var form=$("#epingle form");$("textarea",form).attr("id","texte");if(el.is(".modifevnmt")){var id=el.attr("id").substr(1);var valeurs=evenements[id];var cles=["type","matiere","debut","fin","texte"];for(var i=0;i<6;i++){$("#"+cles[i]).val(valeurs[cles[i]])}$("#id").val(id);$("#texte").change();$("#jours").prop("checked",valeurs["je"]);$('<a class="icon-supprime" title="Supprimer cette information"></a>').insertBefore($(".icon-ok")).on("click",function(){supprime($(this))}).parent().data("id","agenda-elems|"+id)}$("#debut").datetimepicker({onShow:function(){this.setOptions({maxDate:$("#fin").val()||false})},onClose:function(t,input){$("#fin").val(function(i,v){return v||input.val()})}});$("#fin").datetimepicker({onShow:function(){this.setOptions({minDate:$("#debut").val()||false})},onClose:function(t,input){$("#debut").val(function(i,v){return v||input.val()})}});$("#jours").on("change",function(){var v;if(this.checked){$("#debut,#fin").each(function(){v=this.value.split(" ");$(this).val(v[0]).attr("data-heure",v[1]).datetimepicker({format:"d/m/Y",timepicker:false})})}else{$("#debut,#fin").each(function(){if(this.hasAttribute("data-heure"))$(this).val(this.value+" "+$(this).attr("data-heure")).removeAttr("data-heure");$(this).datetimepicker({format:"d/m/Y Ghi",timepicker:true})})}}).change()};function selmult(){var sel=$(this);var isacces=this.getAttribute("name").indexOf("protection")+1?1:0;function majselect(sel){sel.prev().children().prop("selected",false).text(function(){var options=$(isacces?"option:selected:not([value=6])":"option:selected",sel);if(isacces&&options.length==5)return"Tout utilisateur identifié";if(options.length==0)return"Choisir ...";else return options.map(function(){return this.textContent}).get().join(", ")}).prop("selected",true)}$("<select id="+sel.prev().attr("for")+"><option selected hidden></select>").insertBefore(sel.hide(0)).attr("disabled",sel.attr("disabled")).on("click",function(e){e.preventDefault();this.blur();popup('<a class="icon-ok" title="Valider ce choix"></a><h3>'+sel.prev().prev().text().replace(":","")+'</h3><table id="selmult">'+$("option",sel).map(function(){return"<tr"+(this.selected?' class="sel"':"")+"><td>"+this.textContent+'</td><td><input type="checkbox" '+(this.selected?"checked ":"")+'value="'+this.value+'"></td></tr>'}).get().join("")+"</table>",true);var f=$("#fenetre");if(isacces){$("input[value=0],input[value=6],input[value=32]",f).parent().parent().addClass("categorie");$("tr:not(.categorie)",f).addClass("element");$("input",f).on("click",function(){if(this.value==0||this.value==32)$(this).parent().parent().siblings().find("input[type=checkbox]").prop("checked",false).change();else{$("input[value=0],input[value=32]",f).prop("checked",false).change();$("input[value=6]",f).prop("checked",true).change();if(this.value==6)$("tr:not(.categorie) input",f).prop("checked",true).change()}})}else{$("#selmult",f).prepend('<tr class="categorie"><th></th><th><a class="icon-cocher"></a></th></tr>');$(".icon-cocher",f).on("click",cocher_utilisateurs)}$("tr",f).on("click",function(e){if(!$(e.target).is("input"))$(this).find("input").click()});$("input",f).on("change",function(){$(this).parent().parent().removeClass("sel");if(this.checked)$(this).parent().parent().addClass("sel")});$(".icon-ok",f).on("click",function(){sel.val($("input:checked",f).map(function(){return this.value}).get());majselect(sel);$("#fenetre, #fenetre_fond").remove()})});majselect(sel)}function cocher_utilisateurs(){$(this).toggleClass("icon-cocher icon-decocher").parent().parent().nextUntil(".categorie").find("input").prop("checked",$(this).hasClass("icon-decocher")).change()}function init_utilisateurs(){$(".icones.mailenvoi").each(function(){this.innerHTML=this.textContent==1?'<a class="icon-ok" title="Supprimer la possibilité d\'envoyer des courriels"></a>':'<a class="icon-nok" title="Accorder la possibilité d\'envoyer des courriels"></a>'});$(".mailenvoi a").on("click",mail_utilisateur);$("th .icon-mail").on("click",mail_utilisateurs);$(".icon-cocher").on("click",cocher_utilisateurs);$("td .icon-edite").on("click",edite_utilisateur);$("td .icon-desactive, td .icon-active, td .icon-supprutilisateur, td .icon-validutilisateur").on("click",modif_utilisateur);$("th .icon-desactive, th .icon-active, th .icon-supprutilisateur, th .icon-validutilisateur").on("click",modif_utilisateurs);$("td:not(.icones)").on("click",function(e){$(this).parent().find("input").click()});$("#utilisateurs input").on("change",function(){$(this).parent().parent().removeClass("sel");if(this.checked)$(this).parent().parent().addClass("sel")});function mail_utilisateur(){var val=$(this).hasClass("icon-ok");$.ajax({url:"ajax.php",method:"post",data:{action:"utilisateur",modif:"mailenvoi",id:$(this).parent().parent().data("id"),val:1-val},dataType:"json",el:$(this),fonction:function(el){el.toggleClass("icon-ok icon-nok").attr("title",(val?"Accorder":"Supprimer")+" la possibilité d'envoyer des courriels")}})}function edite_utilisateur(){var id=$(this).parent().parent().data("id");$.ajax({url:"recup.php",method:"post",data:{action:"prefs",id:id},dataType:"json",afficheform:function(data){if("nom"in data){popup($("#form-edite").html(),true);var f=$("#fenetre");$("input[name]",f).attr("id",function(){return this.getAttribute("name")});if(data["valide"])$("#comptedesactive, #demande, #invitation",f).remove();else if(data["demande"])$("#compteactif, #comptedesactive, #invitation",f).remove();else if(data["invitation"])$("#compteactif, #comptedesactive, #demande",f).remove();else $("#compteactif, #demande, #invitation",f).remove();if(data["autorisation"]==2)$("#mailliste",f).parent().remove();else if(data["autorisation"]==1)$("#mailenvoi, #mailexp, #mailcopie, #mailliste",f).parent().remove();$("p:first",f).html(function(i,code){return code.replace("XXX",data["prenom"].length?"de <em>"+data["prenom"]+" "+data["nom"]+"</em>":"<em>"+data["login"]+"</em>").replace("YYY","<em>"+["Invité","Élève","Colleur","Administratif","Professeur"][data["autorisation"]-1]+"</em>")});$('input[type="text"],input[type="email"]',f).val(function(){return data[this.id]});$('input[type="checkbox"]',f).prop("checked",function(){return data[this.id]});$("#mailenvoi",f).on("click",function(){$("#mailexp, #mailcopie, #mailliste",f).prop("disabled",!this.checked);if(this.checked&&!$("#mailexp",f).val())$("#mailexp",f).val(data["prenom"]+" "+data["nom"])});$("#mailexp, #mailcopie, #mailliste",f).prop("disabled",!$("#mailenvoi",f).prop("checked"));$("a.icon-ok",f).on("click",function(){$.ajax({url:"ajax.php",method:"post",data:"action=utilisateur&modif=prefs&id="+id+"&"+$("form",f).serialize(),dataType:"json",el:"",fonction:function(el){location.reload(true)}})});$("input",f).on("keypress",function(e){if(e.which==13){e.preventDefault();$("a.icon-ok",f).click()}})}}})}function modif_utilisateur(){var question="";var compte=$(this).parent().siblings().first().text();compte=compte.length?"de <em>"+compte+"</em>":"d'identifiant <em>"+$(this).parent().siblings().first().next().text()+"</em>";var categorie=$(this).parent().parent().prevUntil(".categorie").last().data("val");switch(this.className.substring(5)){case"desactive":if(categorie=="Invités")question="Vous allez désactiver le compte invité "+compte+". Cela signifie que le compte ne sera pas supprimé mais sera non utilisable pour une connexion. Les associations éventuelles avec les matières seront conservées. Ce compte sera listé dans la partie inférieure du tableau.";else question="Vous allez désactiver le compte "+compte+". Cela signifie que le compte sera toujours visible pour les professeurs mais que l'utilisateur correspondant ne pourra plus se connecter. Les notes de colles éventuelles seront conservées. Les données associées au compte seront conservées. Les accès spécifiques éventuels pourront être rétablis en réactivant le compte. Ce compte sera listé dans la partie inférieure du tableau.";break;case"active":if(categorie=="Invités")question="Vous allez réactiver le compte invité "+compte+". La connexion sera à nouveau possible. Ce compte apparaîtra à nouveau dans la partie principale du tableau.";else question="Vous allez réactiver le compte "+compte+". Cela signifie que l'utilisateur correspondant pourra à nouveau se connecter. Il retrouvera son compte, ses notes de colles éventuelles, ses préférences, ses accès spécifiques éventuels, sans modification. Ce compte apparaîtra à nouveau dans la partie principale du tableau.";break;case"supprutilisateur":if(categorie=="Demandes")question="Vous allez supprimer la demande "+compte+". Cela signifie que cette demande ne conduira pas à une création de compte. Le demandeur ne sera pas prévenu de votre décision. Une fois réalisée, cette opération est définitive.";else if(categorie=="Invitations")question="Vous allez supprimer l'invitation "+compte+". Cela signifie que cette invitation ne sera plus valable et que si la personne invitée clique sur le lien reçu par courriel, une erreur apparaîtra devant elle. Cette invitation n'a pas de délai&nbsp;: il est inutile de supprimer l'invitation pour la refaire, à moins de s'être trompé d'adresse électronique. La personne invitée ne sera pas prévenue de votre décision. Une fois réalisée, cette opération est définitive.";else if(categorie=="Professeurs")question="Vous allez supprimer le compte professeur "+compte+". Cela signifie que toutes les préférences de ce compte seront perdues, ainsi que les éventuelles notes de colles. Les données des matières auxquelles il est associé sont indépendantes&nbsp;: elles ne seront pas supprimées. Une fois réalisée, cette opération est définitive.";
-else if(categorie=="Administatifs")question="Vous allez supprimer le compte administratif "+compte+". Cela signifie que toutes les préférences de ce compte seront perdues. Une fois réalisée, cette opération est définitive.";else if(categorie=="Colleurs")question="Vous allez supprimer le compte colleur "+compte+". Cela signifie que toutes les préférences de ce compte seront perdues, ainsi que les éventuelles notes de colles. Une fois réalisée, cette opération est définitive.";else if(categorie=="Élèves")question="Vous allez supprimer le compte élève "+compte+". Cela signifie que toutes les données correspondant à ce compte seront perdues. Les groupes où il apparaît seront modifiés, les notes de colles éventuelles seront supprimées. Une fois réalisée, cette opération est définitive.";else if(categorie=="Invités")question="Vous allez supprimer le compte invité "+compte+". Cela signifie que la connexion par ce compte ne sera plus possible. Une fois réalisée, cette opération est définitive.";else question="Vous allez supprimer le compte "+compte+" déjà désactivé. Cela signifie que toutes les données correspondant à ce compte seront perdues définitivement. Les groupes où il apparaît seront modifiés, les notes de colles éventuelles seront supprimées. Dans le cas d'un compte professeur, les données des matières associées ne seront pas supprimées. Une fois réalisée, cette opération est définitive.";break;case"validutilisateur":question="Vous allez valider la demande "+compte+". Son compte sera immédiatement actif et un courriel va immédiatement être envoyé pour le/la prévenir. Il sera automatiquement associé à toutes les matières, pensez à aller supprimer les matières qui ne le concernent pas sur la page de gestion des associations utilisateurs-matières."}confirmation(question,this,function(el){$.ajax({url:"ajax.php",method:"post",data:{action:"utilisateur",modif:el.className.substring(5),id:$(el).parent().parent().data("id")},dataType:"json",el:"",fonction:function(){location.reload(true)}})})}function mail_utilisateurs(){var cases=$(this).parent().parent().nextUntil(".categorie").find(":checked");if(cases.length==0){affiche("<p>Aucune case n'est cochée, aucune action ne peut être réalisée.</p>","nok");return}var ids=cases.map(function(){return $(this).parent().parent().data("id")}).get().join(",");var tds=cases.parent().prev().prev();var val=tds.find(".icon-ok").length>=tds.find(".icon-nok").length?0:1;$.ajax({url:"ajax.php",method:"post",data:{action:"utilisateurs",modif:"mailenvoi",ids:ids,val:val},dataType:"json",el:"",fonction:function(){location.reload(true)}})}function modif_utilisateurs(){var cases=$(this).parent().parent().nextUntil(".categorie").find(":checked");if(cases.length==0){affiche("<p>Aucune case n'est cochée, aucune action ne peut être réalisée.</p>","nok");return}var ids=cases.map(function(){return $(this).parent().parent().data("id")}).get().join(",");var comptes=cases.map(function(){var compte=$(this).parent().siblings().first().text();return compte.length?"<em>"+compte+"</em>":"<em>"+$(this).parent().siblings().first().next().text()+"</em>"}).get().join(", ");var pos=comptes.lastIndexOf(",");if(pos>0)comptes=comptes.substring(0,pos)+" et"+comptes.substring(pos+1);var question="";var categorie=$(this).parent().parent().prev().children().text().split(" ")[0];switch(this.className.substring(5)){case"desactive":if(categorie=="Invités")question="Vous allez désactiver les comptes invités "+comptes+". Cela signifie que ces compte ne seront pas supprimés mais seront non utilisables pour une connexion. Les associations éventuelles avec les matières seront conservées. Ces comptes seront listés dans la partie inférieure du tableau.";else question="Vous allez désactiver les comptes de "+comptes+". Cela signifie que ces comptes seront toujours visibles pour les professeurs mais que les utilisateurs correspondant ne pourront plus se connecter. Les notes de colles éventuelles seront conservées. Les données associées aux comptes seront conservées. Les accès spécifiques éventuels pourront être rétablis en réactivant les comptes. Ces comptes seront listés dans la partie inférieure du tableau.";break;case"active":if(categorie=="Invités")question="Vous allez réactiver les comptes invité "+comptes+". La connexion sera à nouveau possible. Ces comptes apparaîtront à nouveau dans la partie principale du tableau.";else question="Vous allez réactiver les comptes de "+comptes+". Cela signifie que les utilisateurs correspondant pourront à nouveau se connecter. Ils retrouveront leur compte, leurs notes de colles éventuelles, leurs préférences, leurs accès spécifiques éventuels, sans modification. Ces comptes apparaîtront à nouveau dans la partie principale du tableau.";break;case"supprutilisateur":if(categorie=="Demandes")question="Vous allez supprimer les demandes de "+comptes+". Cela signifie que ces demandes ne conduiront pas à des créations de compte. Les demandeurs ne seront pas prévenus de votre décision. Une fois réalisée, cette opération est définitive.";else if(categorie=="Invitations")question="Vous allez supprimer les invitations de "+comptes+". Cela signifie que ces invitations ne seront plus valables et que si les personnes invitées cliquent sur le lien reçu par courriel, une erreur apparaîtra devant elles. Ces invitations n'ont pas de délai&nbsp;: il est inutile de supprimer une invitation pour la refaire, à moins de s'être trompé d'adresse électronique. Les personnes invitées ne seront pas prévenues de votre décision. Une fois réalisée, cette opération est définitive.";else if(categorie=="Professeurs")question="Vous allez supprimer les comptes professeurs de "+comptes+". Cela signifie que toutes les préférences de ces comptes seront perdues, ainsi que les éventuelles notes de colles. Les données des matières auxquelles ils sont associés sont indépendantes&nbsp;: elles ne seront pas supprimées. Une fois réalisée, cette opération est définitive.";else if(categorie=="Administratifs")question="Vous allez supprimer les comptes administratifs de "+comptes+". Cela signifie que toutes les préférences de ces comptes seront perdues. Une fois réalisée, cette opération est définitive.";else if(categorie=="Colleurs")question="Vous allez supprimer les comptes colleurs de "+comptes+". Cela signifie que toutes les préférences de ces comptes seront perdues, ainsi que les éventuelles notes de colles. Une fois réalisée, cette opération est définitive.";else if(categorie=="Élèves")question="Vous allez supprimer les comptes élèves de "+comptes+". Cela signifie que toutes les données correspondant à ces comptes seront perdues. Les groupes où ils apparaîssent seront modifiés, les notes de colles éventuelles seront supprimées. Une fois réalisée, cette opération est définitive.";else if(categorie=="Invités")question="Vous allez supprimer les comptes invités de "+comptes+". Cela signifie que la connexion par ces comptes ne sera plus possible. Une fois réalisée, cette opération est définitive.";else question="Vous allez supprimer les comptes de "+comptes+" déjà désactivés. Cela signifie que toutes les données correspondant à ces comptes seront perdues définitivement. Les groupes où ils apparaîssent seront modifiés, les notes de colles éventuelles seront supprimées. Dans le cas des comptes professeurs, les données des matières associées ne seront pas supprimées. Une fois réalisée, cette opération est définitive.";break;case"validutilisateur":question="Vous allez valider les demandes de "+comptes+". Leurs comptes seront immédiatement actifs et un courriel va immédiatement leur être envoyé pour les prévenir. Ils seront automatiquement associés à toutes les matières, pensez à aller supprimer les matières qui ne les concernent pas sur la page de gestion des associations utilisateurs-matières."}confirmation(question,this,function(el){$.ajax({url:"ajax.php",method:"post",data:{action:"utilisateurs",modif:el.className.substring(5),ids:ids},dataType:"json",el:"",fonction:function(){location.reload(true)}})})}}function init_utilisateurs_matieres(){$("tbody tr:not(.categorie) td:not(:first-child,:last-child)").each(function(){var valeurs=this.textContent.split("|");this.innerHTML=valeurs[1]==1?'<a class="icon-ok" data-id="'+valeurs[0]+'" title="Supprimer l\'association à la matière"></a>':'<a class="icon-nok" data-id="'+valeurs[0]+'" title="Établir l\'association à la matière"></a>'});$("tbody tr:not(.categorie) a").on("click",association_um);$(".categorie [data-id]").on("click",association_ums).hide(0);$(".icon-cocher").on("click",cocher_utilisateurs).on("click",majicones);$('input[type="checkbox"]').on("click",majicones).on("change",function(){$(this).parent().parent().removeClass("sel");if(this.checked)$(this).parent().parent().addClass("sel")});$("td:first-child").on("click",function(){$(this).parent().find("input").click()});function majicones(){var tr=$(this).parent().parent();if(!tr.hasClass("categorie"))tr=tr.prevAll(".categorie").first();var cases=tr.nextUntil(".categorie").find(":checked");if(cases.length==0){$("[data-id]",tr).hide(0);return}$("[data-id]",tr).each(function(){var avant=$(this).hasClass("icon-ok");var apres=cases.parent().prevAll().find('.icon-ok[data-id="'+this.getAttribute("data-id")+'"]').length<cases.length/2;if(avant!=apres)$(this).toggleClass("icon-ok icon-nok").attr("title",(apres?"Établir":"Supprimer")+" l'association à la matière de tous les cochés")}).show(0)}function association_um(){var val=$(this).hasClass("icon-ok");$.ajax({url:"ajax.php",method:"post",data:{action:"utilisateur-matiere",id:$(this).parent().parent().data("id"),matiere:$(this).data("id"),val:1-val},dataType:"json",el:$(this),fonction:function(el){el.toggleClass("icon-ok icon-nok").attr("title",(val?"Établir":"Supprimer")+" l'association à la matière")}})}function association_ums(){var cases=$(this).parent().parent().nextUntil(".categorie").find(":checked");if(cases.length==0){affiche("<p>Aucune case n'est cochée, aucune action ne peut être réalisée.</p>","nok");return}var ids=cases.map(function(){return $(this).parent().parent().data("id")}).get().join(",");var comptes=cases.map(function(){return $(this).parent().siblings().first().text().split("(")[0].trim()}).get().join(", ");var pos=comptes.lastIndexOf(",");if(pos>0)comptes=comptes.substring(0,pos)+" et"+comptes.substring(pos+1);var val=$(this).hasClass("icon-ok");var mid=this.getAttribute("data-id");var question=val?"Vous allez établir l'association à la matière "+$("#m"+mid).text()+" pour les comptes de "+comptes+". Cela signifie que ces utilisateurs auront accès aux ressources liées à cette matière, en fonction de l'autorisation que vous avez fixée pour ces ressources.":"Vous allez supprimer l'association à la matière "+$("#m"+mid).text()+" pour les comptes de "+comptes+". Cela signifie que ces utilisateurs n'auront plus accès aux ressources liées à cette matière. Si des notes de colles ont été saisies, elles seront automatiquement et définitivement supprimées de la base.";confirmation(question,this,function(el){$.ajax({url:"ajax.php",method:"post",data:{action:"utilisateurs-matieres",ids:ids,matiere:mid,val:val|0},dataType:"json",el:"",fonction:function(el){location.reload(true)}})})}}function init_utilisateurs_groupes(){$('article input[type="checkbox"]').on("change",function(){$.ajax({url:"ajax.php",method:"post",data:{action:"groupes",champ:this.id.substr(0,5),id:this.id.substr(5),val:this.checked|0},dataType:"json",el:"",fonction:function(el){return true}})});$(".usergrp span").append('&nbsp;<a class="icon-edite" title="Éditer les utilisateurs de ce groupe"></a>').on("click",utilisateursgroupe)}function utilisateursgroupe(){popup($("#form-utilisateurs").html(),true);var f=$("#fenetre");var span=$(this);article=span.parent().parent();$("table",f).attr("id","utilisateurs");$("h3",f).append($(".editable",article).text()||$("input:first",article).val());$(".icon-deplie",f).on("click",plie);$(".icon-cocher",f).on("click",cocher_utilisateurs);$("tr:not(.categorie)",f).on("click",function(e){if(!$(e.target).is("input"))$(this).find("input").click()});$("input",f).on("change",function(){$(this).parent().parent().removeClass("sel");if(this.checked)$(this).parent().parent().addClass("sel")});var ids=span.data("uids");$("#u"+ids.replace(/,/g,",#u"),f).prop("checked",true).change();$(".icon-ok",f).on("click",function(){var ids=$("input:checked",f).map(function(){return this.id.replace("u","")}).get().join(",");var noms=$("input:checked",f).parent().prev().map(function(){return this.textContent.split("(")[0].trim()}).get().join(", ")||"[Personne]";if(article.is("div")){$("#uids",article).val(ids);span.data("uids",ids);span.html(noms+'&nbsp;<a class="icon-edite" title="Éditer les utilisateurs de ce groupe"></a>');$("#fenetre, #fenetre_fond").remove()}else $.ajax({url:"ajax.php",method:"post",data:{action:"groupes",champ:"utilisateurs",id:article.data("id").split("|")[1],uids:ids},dataType:"json",el:span,fonction:function(el){el.data("uids",ids);el.html(noms+'&nbsp;<a class="icon-edite" title="Éditer les utilisateurs de ce groupe"></a>');$("#fenetre, #fenetre_fond").remove()}})})}function suppressionmultiple(){var prop=$(this).data("id").split("|");var contexte=$(this).parent().find("h3").text();var item="";switch(prop[2]){case"infos":item="toutes les informations de la page <em>"+contexte+"</em>";break;case"colles":item="tous les programmes de colles de la matière <em>"+contexte+"</em>";break;case"cdt":item="tout le contenu du cahier de texte de la matière <em>"+contexte+"</em>";break;case"docs":item="tous les répertoires et documents de la matière <em>"+contexte+"</em>";break;case"notes":item="toutes les notes de la matière <em>"+contexte+"</em>";break}confirmation("Vous allez supprimer XXX.<br>Cette opération n'est pas annulable.".replace("XXX",item),this,function(el){$.ajax({url:"ajax.php",method:"post",data:"action="+prop[0]+"&id="+prop[1]+"&supprime_"+prop[2]+"=1",dataType:"json",el:$(el),fonction:function(el){el.remove()}})})}function destinatairesmail(){popup($("#form-destinataires").html(),true);var f=$("#fenetre");$("table",f).attr("id","utilisateurs");$(".icon-deplie",f).on("click",plie);$("tr:not(.gr) input.dest",f).attr("id",function(){return"u"+this.value});$("tr:not(.categorie) td:nth-child(-n+2)",f).on("click",function(e){if(!$(e.target).is("input"))$(this).parent().find("input:first").click()});$("input",f).on("change",function(){var tr=$(this).parent().parent().removeClass("sel");if(this.checked)tr.find("input:not(."+this.className+")").prop("checked",false);if(tr.find("input:checked").length)tr.addClass("sel")});var ids=$('[name="id-copie"]').val();$("#u"+ids.replace(/,/g,",#u")).prop("checked",true).change();ids=$('[name="id-bcc"]').val();$("#u"+ids.replace(/,/g,",#u")).parent().next().children().prop("checked",true).change();$(".categorie a",f).on("click keyup",function(){var classe=this.className.split(" ")[1];var etat=this.className.split(" ")[0]=="icon-cocher";var titre=this.title;$(this).parent().parent().nextUntil(".categorie").find("."+classe+":not(:disabled)").prop("checked",etat).change();this.className=(etat?"icon-decocher ":"icon-cocher ")+classe;this.title=this.title.replace(etat?"Cocher":"Décocher",etat?"Décocher":"Cocher");var classe2=classe=="dest"?"bcc":"dest";$(this).parent().parent().find(".icon-decocher."+classe2).each(function(){this.className="icon-cocher "+classe2;this.title="C"+this.title.substr(3)})});$(".gr input",f).on("click",function(){var ids=this.value;if(this.className=="dest")$("#u"+ids.replace(/,/g,",#u")).prop("checked",this.checked).change();else $("#u"+ids.replace(/,/g,",#u")).parent().next().children().prop("checked",this.checked).change()});$(".icon-ok",f).on("click",function(){$('[name="id-copie"]').val($("tr:not(.gr) .dest:checked",f).map(function(){return this.value}).get().join(","));$('[name="id-bcc"]').val($("tr:not(.gr) .bcc:checked",f).map(function(){return this.value}).get().join(","));$("#maildest").text($("tr:not(.gr) .dest:checked",f).parent().prev().map(function(){return this.textContent}).get().concat($("tr:not(.gr) .bcc:checked",f).parent().prev().prev().map(function(){return this.textContent+" (CC)"}).get()).join(", ")||"[Personne]");$("#fenetre, #fenetre_fond").remove()})}function envoimail(){if($(".maildest").children("span").text()=="[Personne]")affiche("Il faut au moins un destinataire pour envoyer le courriel.","nok");else if(!$('[name="sujet"]').val().length)affiche("Il faut un sujet non vide pour envoyer le courriel.","nok");else $.ajax({url:"ajax.php",method:"post",data:$("#mail").serialize(),dataType:"json",el:"",fonction:function(el){location.reload(true)}})}function relevenotes(){confirmation("<p>Vous allez réaliser une relève des notes de colles. Cela consiste à marquer comme relevées toutes les heures déclarées jusqu'à maintenant et non encore relevées. Vous pourrez alors télécharger le nouveau relevé au sein du tableau en bas de page.</p><p>Cette opération n'est pas annulable.</p><p>Une fois que vous aurez réalisé ce relevé, les professeurs et colleurs ne pourront pas modifier le nombre d'élèves et la durée correspondant aux colles relevées.</p>",this,function(el){$.ajax({url:"ajax.php",method:"post",data:"action=releve-notes",dataType:"json",el:"",fonction:function(el){location.reload(true)}})})}$(document).ajaxSend(function(ev,xhr,settings){$("#load").show(200);if(settings.data.append)settings.data.append("csrf-token",$("body").attr("data-csrf-token"));else settings.data="csrf-token="+$("body").attr("data-csrf-token")+"&"+settings.data}).ajaxStop(function(){$("#load").hide(200)}).ajaxSuccess(function(ev,xhr,settings){var data=xhr.responseJSON;switch(data["etat"]){case"ok":affiche(data["message"],"ok");settings.fonction(settings.el);break;case"nok":affiche(data["message"],"nok");break;case"login":case"mdp":reconnect(settings,data["etat"]=="mdp");break;case"recupok":settings.afficheform(data)}});$(function(){$("a.formulaire, .modifevnmt").on("click",formulaire);$("a.icon-aide").on("click",function(){popup($("#aide-"+($(this).parent().data("id")||"page").split("|")[0]).html(),false)});$("a.icon-ok").on("click",valide);$("a.icon-cache,a.icon-montre,a.icon-monte,a.icon-descend,a.icon-supprime,a.icon-lock,a.icon-ajoutecolle").on("click",function(){window[this.className.substring(5)]($(this))});$("#log").hide().on("click",function(){$(this).hide(300)});$(".editable").editinplace();$("a.icon-deconnexion").on("click",function(e){$.ajax({url:"ajax.php",method:"post",data:{action:"deconnexion"},dataType:"json",el:"",fonction:function(el){location.reload(true)}})});$(".titrecdt").editinplacecdt();$(".cdt-raccourcis").init_cdt_raccourcis();$(".icon-mailenvoi").on("click",envoimail);$("#maildest, #maildest + .icon-edite").on("click",destinatairesmail);$(".categorie th:first-child").prepend($('<span class="icon-deplie" title="Déplier/Replier cette catégorie"></span>').on("click",plie));$("article select[multiple]").each(selmult);$(".supprmultiple").on("click",suppressionmultiple);$("#utilisateurs").each(init_utilisateurs);$("#utilisateurs-matieres").each(init_utilisateurs_matieres);$(".usergrp").first().each(init_utilisateurs_groupes);$("#planning select").change(function(){$(this).parent().prev().children("input").prop("checked",this.value==0)});$("#planning input").change(function(){$(this).parent().next().children("select").val(0)});$("#relevenotes").on("click",relevenotes);$(".icon-menu").on("click",function(){$("#colonne,nav").toggleClass("visible")})});
\ No newline at end of file
diff -urN cahier-de-prepa8.0.2/js/edition.min.js cahier-de-prepa8.1.0/js/edition.min.js
--- cahier-de-prepa8.0.2/js/edition.min.js	1970-01-01 01:00:00.000000000 +0100
+++ cahier-de-prepa8.1.0/js/edition.min.js	2018-10-31 03:51:26.586252895 +0100
@@ -0,0 +1,3 @@
+function affiche(message,etat){$("#log").removeClass().addClass(etat).html(message).append('<span class="icon-ferme"></span>').fadeIn().off("click").on("click",function(){window.clearTimeout(extinction);$(this).fadeOut(800)});extinction=window.setTimeout(function(){$("#log").fadeOut(800)},6e3)}function reconnect(settings,light){$("#fenetre,#fenetre_fond").remove();if(settings.url=="recup.php")var action=settings.data.indexOf("prefs")?"récupérer les préférences de cet utilisateur":"récupérer la liste des répertoires et documents disponibles";else{var action="valider cette action";settings.afficheform=Function.prototype}if(light)popup('<a class="icon-ok" title="Valider"></a><h3>Connexion nécessaire</h3>           <p>Vous êtes déjà connecté, mais vous devez saisir de nouveau votre mot de passe pour '+action+'.</p>           <form>           <p class="ligne"><label for="motdepasse">Mot de passe&nbsp;: </label><input type="password" name="motdepasse" id="motdepasse"></p>           </form>',true);else popup('<a class="icon-ok" title="Valider"></a><h3>Connexion nécessaire</h3>           <p>Vous avez été automatiquement déconnecté. Vous devez vous connecter à nouveau pour '+action+'.</p>           <form>           <p class="ligne"><label for="login">Identifiant&nbsp;: </label><input type="text" name="login" id="login"></p>           <p class="ligne"><label for="motdepasse">Mot de passe&nbsp;: </label><input type="password" name="motdepasse" id="motdepasse"></p>           </form>',true);$("#fenetre input:first").focus();$("#fenetre a.icon-ok").on("click",function(){$.ajax({url:settings.url,method:"post",data:$("#fenetre form").serialize()+"&"+settings.data,dataType:"json",el:settings.el,afficheform:settings.afficheform,fonction:settings.fonction}).done(function(data){if(data["etat"]!="mdpnok")$("#fenetre,#fenetre_fond").remove()})});$("#fenetre a.icon-ferme").on("click",function(){affiche("Modification non effectuée, connexion nécessaire","nok")});$("#fenetre input").on("keypress",function(e){if(e.which==13){$("#fenetre a.icon-ok").click();return false}})}function popup(contenu,modal){$("#fenetre,#fenetre_fond").remove();var el=$('<article id="fenetre"></article>').appendTo("body").html(contenu).focus();if(modal)$('<div id="fenetre_fond"></div>').appendTo("body").click(function(){$("#fenetre,#fenetre_fond").remove()});else $('<a class="icon-epingle" title="Épingler à la page"></a>').prependTo(el).on("click",function(){$("#fenetre_fond").remove();$(this).remove();el.removeAttr("id").insertBefore($("article,#calendrier,#parentsdoc+*").first())});$('<a class="icon-ferme" title="Fermer"></a>').prependTo(el).on("click",function(){el.remove();$("#fenetre_fond").remove()})}function confirmation(question,element,action){popup("<h3>Demande de confirmation</h3><p>"+question+'</p><p class="confirmation"><button class="icon-ok"></button>&nbsp;&nbsp;&nbsp;<button class="icon-annule"></button></p>',true);$("#fenetre .icon-ok").on("click",function(){action(element);$("#fenetre,#fenetre_fond").remove()});$("#fenetre .icon-annule").on("click",function(){$("#fenetre,#fenetre_fond").remove()})}function plie(){$(this).parent().parent().nextUntil(".categorie").fadeToggle("slow");$(this).toggleClass("icon-plie icon-deplie")}$.fn.textareahtml=function(){this.each(function(){var ta=$(this);var placeholder=this.getAttribute("placeholder");this.setAttribute("placeholder",placeholder+". Formattage en HTML, balises visibles.");var ce=$('<div contenteditable="true" placeholder="'+placeholder+'"></div>').insertAfter(ta.before(boutons)).hide();var boutonretour=ta.prev().children(".icon-retour");if(ta.hasClass("ligne")){ce.addClass("ligne");ta.prev().addClass("ligne")}ta.on("keypress",function(e){if(e.which==13)this.value=nettoie(this.value)}).on("paste cut",function(){var el=this;setTimeout(function(){el.value=nettoie(el.value)},100)});ce.on("keypress",function(e){if(e.which==13)boutonretour.click()}).on("paste cut",function(){var el=this;setTimeout(function(){el.innerHTML=nettoie(el.innerHTML)+"<br>"},100)});ta.prev().children(".icon-nosource").on("click",function(e){e.preventDefault();ta.hide();ce.show().css("min-height",ta.outerHeight());$(this).hide().prev().show();ce.focus().html(nettoie(ta.val())).change();if(window.getSelection){var r=document.createRange();r.selectNodeContents(ce[0]);r.collapse(false);var s=window.getSelection();s.removeAllRanges();s.addRange(r)}else{var r=document.body.createTextRange();r.moveToElementText(ce[0]);r.collapse(false);r.select()}});ta.prev().children(".icon-source").on("click",function(e){e.preventDefault();ce.hide(0);ta.show(0).css("height",ce.height());$(this).hide().next().show();ta.focus().val(nettoie(ce.html()))}).hide();ta.prev().children(".icon-aide").on("click",function(e){e.preventDefault();aidetexte()});ta.prev().children().not(".icon-nosource,.icon-source,.icon-aide").on("click",function(e){e.preventDefault();window["insertion_"+this.className.substring(5)]($(this))})})};$.fn.editinplace=function(){this.each(function(){var el=$(this);el.data("original",el.is("h3")?el.text():el.html());$('<a class="icon-edite" title="Modifier"></a>').appendTo(el).on("click",transforme)})};function transforme(){var el=$(this).parent().addClass("avecform");if(el.is("div"))el.html('<form><textarea name="val" rows="'+(el.data("original").split(/\r\n|\r|\n/).length+3)+'"></textarea></form>');else el.html('<form class="edition" onsubmit="$(this).children(\'a.icon-ok\').click(); return false;"><input type="text" name="val" value=""></form>');var input=el.find('[name="val"]').val(el.data("original")).attr("placeholder",el.attr("placeholder"));if(el.hasClass("edithtml"))input.textareahtml();$('<a class="icon-ok" title="Valider"></a>').appendTo(el.children()).on("click",function(){var id=el.data("id").split("|");if(el.hasClass("edithtml"))input.val(nettoie(input.is(":visible")?input.val():input.next().html()));$.ajax({url:"ajax.php",method:"post",data:{action:id[0],champ:id[1],id:id[2],val:input.val()},dataType:"json",el:el,fonction:function(el){var val=el.find('[name="val"]').val();el.removeClass("avecform").html(val).data("original",val);$('<a class="icon-edite" title="Modifier"></a>').appendTo(el).on("click",transforme)}})});$('<a class="icon-annule" title="Annuler"></a>').appendTo(el.children()).on("click",function(){el.removeClass("avecform").html(el.data("original"));$('<a class="icon-edite" title="Modifier"></a>').appendTo(el).on("click",transforme)});input.focus().val(el.hasClass("edithtml")?nettoie(input.val()):input.val())}$.fn.editinplacecdt=function(){this.each(function(){$(this).wrapInner("<span></span>").data("original",$(this).text());$('<a class="icon-edite" title="Modifier"></a>').appendTo($(this)).on("click",transformecdt)})};function transformecdt(){var el=$(this).parent();$(".icon-edite",el).remove();var form=$('<form class="titrecdt"></form>').insertBefore(el.parent().children("div")).html($("#form-cdt").html());$("input, select",form).attr("id",function(){return this.getAttribute("name")});var valeurs=el.data("donnees");for(var cle in valeurs)$("#"+cle).val(valeurs[cle]);form.init_cdt_boutons();$("input,#demigroupe",form).on("change keyup",function(){var t=new Date($("#jour").val().replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z){return z+"-"+y+"-"+x}));var dg=$("#demigroupe").val()==1?" (en demi-groupe)":"";switch(parseInt(seances[$("#tid").val()])){case 0:var titre=jours[t.getDay()]+" "+$("#jour").val()+" à "+$("#h_debut").val()+" : "+$("#tid option:selected").text()+dg;break;case 1:var titre=jours[t.getDay()]+" "+$("#jour").val()+" de "+$("#h_debut").val()+" à "+$("#h_fin").val()+" : "+$("#tid option:selected").text()+dg;break;case 2:var titre=jours[t.getDay()]+" "+$("#jour").val()+" : "+$("#tid option:selected").text()+" pour le "+$("#pour").val()+dg;break;case 3:var titre=jours[t.getDay()]+" "+$("#jour").val()+" : "+$("#tid option:selected").text()+dg;break;case 4:var titre=jours[t.getDay()]+" "+$("#jour").val();break;case 5:var titre="[Entrée hebdomadaire]"}$("span",el).text(titre)});$('<a class="icon-ok" title="Valider"></a>').appendTo(el).on("click",function(){var id=el.parent().data("id").split("|");$.ajax({url:"ajax.php",method:"post",data:"action=cdt-elems&id="+id[1]+"&"+form.serialize(),dataType:"json",el:el,fonction:function(el){var form=el.siblings("form");el.data("original",$("span",el).text()).data("donnees",{tid:$("#tid").val(),jour:$("#jour").val(),h_debut:$("#h_debut").val(),h_fin:$("#h_fin").val(),pour:$("#pour").val(),demigroupe:$("#demigroupe").val()});form.remove();$("a",el).remove();$('<a class="icon-edite" title="Modifier"></a>').appendTo(el).on("click",transformecdt)}}).done(function(data){if(data["etat"]=="ok"&&data["reload"]=="oui")location.reload(true)})});$('<a class="icon-annule" title="Annuler"></a>').appendTo(el).on("click",function(){form.remove();$("span",el).html(el.data("original"));$("a",el).remove();$('<a class="icon-edite" title="Modifier"></a>').appendTo(el).on("click",transformecdt)})}function nettoie(html){if(html.indexOf("cdptmp")>0){var tmp=$("<div>"+html+"</div>");tmp.find(".cdptmp").contents().unwrap();html=tmp.html();if(html.indexOf("cdptmp")>0)html=html.replace(/<span class="cdptmp"><\/span>/g,"")}return html.replace(/(<\/?[A-Z]+)([^>]*>)/g,function(tout,x,y){return x.toLowerCase()+y}).replace(/[\r\n ]+/g," ").replace(/(<br>)+[ ]?<\/(p|div|li|h)/g,function(tout,x,y){return"</"+y}).replace(/<br>/g,"<br>\n").replace(/<(p|div|li|h)/g,function(x){return"\n"+x}).replace(/<\/(p|div|li|h.)>/g,function(x){return x+"\n"}).replace(/<\/?(ul|ol)[^>]*>/g,function(x){return"\n"+x+"\n"}).replace(/^(?!(<p|<div|<ul|<ol|<li|<h))(.+)<br>$/gm,function(tout,x,y){return"<p>"+y+"</p>"}).replace(/^(?!(<(p|div|ul|ol|li)))[ ]?(.+)[ ]?$/gm,function(t,x,y,z){return z.match(/.*(p|div|ul|ol|li|h.)>$/)?z:"<p>"+z+"</p>"}).replace(/^[ ]?(<\/?(br|p|div|h.)>){0,2}[ ]?(<\/(p|div|h.)>)?[ ]?$/gm,"").replace(/^\n/gm,"").replace(/<li/g,"  <li")}function insert(el,debut,fin,milieu){var contenant=el.parent().siblings("textarea,[contenteditable]").filter(":visible")[0];if(!contenant.hasAttribute("data-selection"))marqueselection(el);var texte=milieu===undefined?debut+"Í"+contenant.getAttribute("data-selection")+"Ì"+fin:debut+"Í"+milieu+"Ì"+fin;var contenu=nettoie(contenant.getAttribute("data-contenu").replace(/Í.*Ì/,texte));if(contenant.tagName=="TEXTAREA")contenant.value=contenu.replace(/[ÍÌ]/g,"");else contenant.innerHTML=contenu.replace(/[ÍÌ]/g,"");marqueselection(el,true);if(contenant.tagName=="TEXTAREA"&&contenant.selectionStart!==undefined){contenant.selectionStart=contenu.indexOf("Í");contenant.selectionEnd=contenu.indexOf("Ì")-1;contenant.focus()}else if(document.selection){if(contenant.tagName!="TEXTAREA")contenu=contenu.replace(/(<([^>]+)>)[\n]*/g,"");range=document.body.createTextRange();range.moveToElementText(contenant);range.collapse(true);range.moveEnd("character",contenu.indexOf("Ì")-1);range.moveStart("character",contenu.indexOf("Í"));range.select()}else if(window.getSelection){contenant.innerHTML=contenu.replace("Í",'<span class="cdptmp">').replace("Ì","</span>")+"<br>";selection=window.getSelection();range=document.createRange();range.selectNodeContents($(contenant).find(".cdptmp")[0]);selection.removeAllRanges();selection.addRange(range);contenant.focus()}}function marqueselection(el,efface){var contenant=el.parent().siblings("textarea,[contenteditable]").filter(":visible")[0];if(efface){contenant.removeAttribute("data-selection");contenant.removeAttribute("data-contenu");return true}var original=contenant.tagName=="TEXTAREA"?contenant.value:contenant.innerHTML;var sel="";if(contenant.tagName=="TEXTAREA"&&contenant.selectionStart!==undefined){contenant.focus();sel=contenant.value.substring(contenant.selectionStart,contenant.selectionEnd);contenant.value=contenant.value.substr(0,contenant.selectionStart)+"Í"+sel+"Ì"+contenant.value.substring(contenant.selectionEnd)}else if(window.getSelection){var range=window.getSelection().getRangeAt(0);if(contenant==range.commonAncestorContainer||$.contains(contenant,range.commonAncestorContainer)){var sel=window.getSelection().toString();range.deleteContents();range.insertNode(document.createTextNode("Í"+sel+"Ì"))}}else{var range=document.selection.createRange();if(contenant==range.parentElement()||$.contains(contenant,range.parentElement())){var sel=document.selection.createRange().text;document.selection.createRange().text="Í"+sel+"Ì"}}if(contenant.tagName=="TEXTAREA"){var contenu=contenant.value;contenant.value=original}else{var contenu=contenant.innerHTML;$(contenant).html(original)}if(contenu.indexOf("Ì")<0)contenu=contenu+"ÍÌ";contenant.setAttribute("data-selection",sel);contenant.setAttribute("data-contenu",contenu);return sel}var boutons='<p class="boutons">  <button class="icon-titres" title="Niveaux de titres"></button>  <button class="icon-par1" title="Paragraphe"></button>  <button class="icon-par2" title="Paragraphe important"></button>  <button class="icon-par3" title="Paragraphe très important"></button>  <button class="icon-retour" title="Retour à la ligne"></button>  <button class="icon-gras" title="Gras"></button>  <button class="icon-italique" title="Italique"></button>  <button class="icon-souligne" title="Souligné"></button>  <button class="icon-omega" title="Insérer une lettre grecque"></button>  <button class="icon-sigma" title="Insérer un signe mathématique"></button>  <button class="icon-exp" title="Exposant"></button>  <button class="icon-ind" title="Indice"></button>  <button class="icon-ol" title="Liste énumérée"></button>  <button class="icon-ul" title="Liste à puces"></button>  <button class="icon-lien1" title="Lien vers un document du site"></button>  <button class="icon-lien2" title="Lien internet"></button>  <button class="icon-tex" title="LATEX!"></button>  <button class="icon-source" title="Voir et éditer le code html"></button>  <button class="icon-nosource" title="Voir et éditer le texte formaté"></button>  <button class="icon-aide" title="Aide pour cet éditeur de texte"></button></p>';function insertion_titres(el){popup('<a class="icon-ok" title="Valider"></a><h3>Insertion d\'un titre</h3>  <p>Choisissez le type du titre ci-dessous. Vous pouvez éventuellement modifier le texte (ou pourrez le faire ultérieurement). Il est conseillé d\'utiliser des titres de niveau 2 pour les titres dans les programmes de colle.</p>  <input type="radio" name="titre" id="t3" value="3" checked><h3><label for="t3">Titre de niveau 1 (pour les I,II...)</label></h3><br>  <input type="radio" name="titre" id="t4" value="4"><h4><label for="t4">Titre de niveau 2 (pour les 1,2...)</label></h4><br>  <input type="radio" name="titre" id="t5" value="5"><h5><label for="t5">Titre de niveau 3 (pour les a,b...)</label></h5><br>  <input type="radio" name="titre" id="t6" value="6"><h6><label for="t6">Titre de niveau 4</label></h6><br>  <p class="ligne"><label for="texte">Texte&nbsp;: </label><input type="text" id="texte" value="'+marqueselection(el)+'" size="80"></p>  <hr><h3>Aperçu</h3><div id="apercu"></div>',true);$("#fenetre input").on("click keyup",function(){var balise="h"+$("[name='titre']:checked").val();$("#apercu").html("<"+balise+">"+($("#texte").val().length?$("#texte").val():"Texte du titre")+"</"+balise+">")}).first().keyup();$("#texte").on("keypress",function(e){if(e.which==13)$("#fenetre a.icon-ok").click()}).focus();$("#fenetre a.icon-ok").on("click",function(){var balise="h"+$("[name='titre']:checked").val();insert(el,"<"+balise+">","</"+balise+">",$("#texte").val());$("#fenetre,#fenetre_fond").remove()});$("#fenetre a.icon-ferme,#fenetre_fond").on("click",function(){marqueselection(el,true)})}function insertion_omega(el){popup("<h3>Insertion d'une lettre grecque</h3>  <p>Cliquez sur la lettre à insérer&nbsp;:</p>  <button>&alpha;</button> <button>&beta;</button> <button>&gamma;</button> <button>&Delta;</button> <button>&delta;</button> <button>&epsilon;</button> <button>&eta;</button> <button>&Theta;</button> <button>&theta;</button> <button>&Lambda;</button> <button>&lambda;</button> <button>&mu;</button> <button>&nu;</button> <button>&xi;</button> <button>&Pi;</button> <button>&pi;</button> <button>&rho;</button> <button>&Sigma;</button> <button>&sigma;</button> <button>&tau;</button> <button>&upsilon;</button> <button>&Phi;</button> <button>&phi;</button> <button>&Psi;</button> <button>&psi;</button> <button>&Omega;</button> <button>&omega;</button>",true);$("#fenetre button").on("click",function(){insert(el,"","",$(this).text());$("#fenetre,#fenetre_fond").remove()})}function insertion_sigma(el){popup("<h3>Insertion d'un symbole mathématique</h3>  <p>Cliquez sur le symbole à insérer&nbsp;:</p>  <button>&forall;</button> <button>&exist;</button> <button>&part;</button> <button>&nabla;</button> <button>&prod;</button> <button>&sum;</button> <button>&plusmn;</button> <button>&radic;</button> <button>&infin;</button> <button>&int;</button> <button>&prop;</button> <button>&sim;</button> <button>&cong;</button> <button>&asymp;</button> <button>&ne;</button> <button>&equiv;</button> <button>&le;</button> <button>&ge;</button> <button>&sub;</button> <button>&sup;</button> <button>&nsub;</button> <button>&sube;</button> <button>&supe;</button> <button>&isin;</button> <button>&notin;</button> <button>&ni;</button> <button>&oplus;</button> <button>&otimes;</button> <button>&sdot;</button> <button>&and;</button> <button>&or;</button> <button>&cap;</button> <button>&cup;</button> <button>&real;</button> <button>&image;</button> <button>&empty;</button> <button>&deg;</button> <button>&prime;</button> <button>&micro;</button> <button>&larr;</button> <button>&uarr;</button> <button>&rarr;</button> <button>&darr;</button> <button>&harr;</button> <button>&lArr;</button> <button>&uArr;</button> <button>&rArr;</button> <button>&dArr;</button> <button>&hArr;</button>",true);$("#fenetre button").on("click",function(){insert(el,"","",$(this).text());$("#fenetre,#fenetre_fond").remove()})}function insertion_ol(el){popup('<a class="icon-ok" title="Valider"></a><h3>Insertion d\'une liste numérotée</h3>  <p>Choisissez le type de numérotation et la valeur de départ de la liste ci-dessous. Vous pouvez éventuellement modifier les différents éléments en les écrivant ligne par ligne. Vous pourrez ajouter un élément ultérieurement en l\'encadrant par les balises &lt;li&gt; et &lt;/li&gt;.</p>  <p class="ligne"><label for="t1">Numérotation numérique (1, 2, 3...)</label><input type="radio" name="type" id="t1" value="1" checked></p>  <p class="ligne"><label for="t2">Numérotation alphabétique majuscule (A, B, C...)</label><input type="radio" name="type" id="t2" value="A"></p>  <p class="ligne"><label for="t3">Numérotation alphabétique minuscule (a, b, c...)</label><input type="radio" name="type" id="t3" value="a"></p>  <p class="ligne"><label for="t4">Numérotation romaine majuscule (I, II, III...)</label><input type="radio" name="type" id="t4" value="I"></p>  <p class="ligne"><label for="t5">Numérotation romaine minuscule (i, ii, iii...)</label><input type="radio" name="type" id="t5" value="i"></p>  <p class="ligne"><label for="debut">Valeur de début (numérique)</label><input type="text" id="debut" value="1"></p>  <p class="ligne"><label for="lignes">Textes (chaque ligne correspond à un élément de la liste)&nbsp;: </label></p>  <textarea id="lignes" rows="5">'+marqueselection(el)+'</textarea>  <hr><h3>Aperçu</h3><div id="apercu"></div>',true);$("#fenetre :input").on("click keyup",function(){var debut=$("#debut").val();debut=debut.length&&debut>1?' start="'+debut+'"':"";$("#apercu").html('<ol type="'+$("[name='type']:checked").val()+'"'+debut+"><li>"+($("#lignes").val().length?$("#lignes").val().trim("\n").replace(/\n/g,"</li><li>"):"Première ligne</li><li>Deuxième ligne</li><li>...")+"</li></ol>")}).first().keyup();$("#lignes").focus();$("#fenetre a.icon-ok").on("click",function(){var debut=$("#debut").val();debut=debut.length&&debut>1?' start="'+debut+'"':"";var elements=$("#lignes").val().trim("\n");var index=elements.lastIndexOf("\n");if(index>0){var dernier=elements.substring(index+1);elements=elements.substring(0,index)}else var dernier="";insert(el,'<ol type="'+$("[name='type']:checked").val()+'"'+debut+"><li>"+elements.replace(/\n/g,"</li><li>")+"</li><li>","</li></ol>",dernier);$("#fenetre,#fenetre_fond").remove()});$("#fenetre a.icon-ferme,#fenetre_fond").on("click",function(){marqueselection(el,true)})}function insertion_ul(el){popup('<a class="icon-ok" title="Valider"></a><h3>Insertion d\'une liste à puces</h3>  <p>Vous pouvez éventuellement modifier les différents éléments en les écrivant ligne par ligne (chaque ligne correspond à un élément de la la liste). Vous pourrez ajouter un élément ultérieurement en l\'encadrant par les balises &lt;li&gt; et &lt;/li&gt;.</p>  <textarea id="lignes" rows="5">'+marqueselection(el)+'</textarea>  <hr><h3>Aperçu</h3><div id="apercu"></div>',true);$("#lignes").on("click keyup",function(){$("#apercu").html("<ul><li>"+($("#lignes").val().length?$("#lignes").val().trim("\n").replace(/\n/g,"</li><li>"):"Première ligne</li><li>Deuxième ligne</li><li>...")+"</li></ul>")}).keyup().focus();$("#fenetre a.icon-ok").on("click",function(){var elements=$("#lignes").val().trim("\n");var index=elements.lastIndexOf("\n");if(index>0){var dernier=elements.substring(index+1);elements=elements.substring(0,index)}else var dernier="";insert(el,"<ul><li>"+elements.replace(/\n/g,"</li><li>")+"</li><li>","</li></ul>",dernier);$("#fenetre,#fenetre_fond").remove()});$("#fenetre a.icon-ferme,#fenetre_fond").on("click",function(){marqueselection(el,true)})}function insertion_lien1(el){var sel=marqueselection(el);popup('<a class="icon-ok" title="Valider"></a><h3>Insertion d\'un lien vers un document de Cahier de Prépa</h3>  <div><p style="text-align:center; margin: 2em 0;">[Récupération des listes de documents]</p></div>  <div style="display:none;"><hr><h3>Aperçu</h3><div id="apercu" style="text-align:center;">[Veuillez choisir un document]</div></div>',true);$("#fenetre a.icon-ferme,#fenetre_fond").on("click",function(){marqueselection(el,true)});$.ajax({url:"recup.php",method:"post",data:{action:"docs"},dataType:"json"}).done(function(data){var majapercu=function(){var apercu=$("#apercu");var id=$("#doc").val();var texte=$("#doc option:selected").text();if(id==0)apercu.html(texte);else if($("#vue").is(":checked")){var l=$("#largeur").val();if(texte.slice(-4,-1)=="pdf"){if(apercu.children(".pdf").length==0)apercu.html('<div><object data="download?id='+id+'" type="application/pdf" height="100%" width="100%"> <a href="download?id='+id+'">'+texte+"</a> </object></div>");else if(apercu.find("object").attr("data").substr(12)!=id)apercu.find("object").attr("data","download?id="+id).html('<a href="download?id='+id+'">'+texte+"</a>");apercu.children().attr("class","pdf "+$("#format").val());if(l){if(l==100)apercu.children().removeAttr("style").children().attr("width","100%").removeAttr("style");else{apercu.children().css("padding-bottom",$('<div class="'+$("#format").val()+'"></div>').css("padding-bottom").slice(0,-1)*l/100+"%");apercu.find("object").attr("width",l+"%").css("left",(100-l)/2+"%")}}}else if("jpgpegpng".indexOf(texte.slice(-4,-1))>-1){if(apercu.children("img").length==0)apercu.css("text-align","").html('<img src="download?id='+id+'">');else if(apercu.children().attr("src").substr(12)!=id)apercu.children().attr("src","download?id="+id);if(l){if(l==100)apercu.children().removeAttr("style");else apercu.children().css("width",l+"%").css("margin-left",(100-l)/2+"%")}}}else $("#apercu").css("text-align","center").html('<a onclick="return false;" href="download?id='+this.value+'">'+$("#texte").val()+"</a>")};var affichedocs=function(data){$("#fenetre > div:first").html('  <p>Choisissez ci-dessous le répertoire puis le document à insérer. Vous pouvez aussi modifier le texte visible. Cela reste modifiable ultérieurement&nbsp;: le texte est situé entre les deux balises &lt;a...&gt; et &lt;/a&gt;.</p>  <p class="ligne"><label for="mat">Matière&nbsp;:</label><select id="mat">'+data.mats+'</select></p>  <p class="ligne"><label for="rep">Répertoire&nbsp;:</label><select id="rep"></select></p>  <p class="ligne"><label for="doc">Document&nbsp;:</label><select id="doc"></select></p>  <p class="ligne"><label for="texte">Texte visible&nbsp;:</label><input type="text" id="texte" value="'+sel+'" size="80" data-auto="1"></p>  <p class="ligne"><label for="vue">Afficher dans la page (PDF et image uniquement)</label><input type="checkbox" id="vue">  <p class="ligne"><label for="largeur">Largeur en %&nbsp;:</label><input type="text" id="largeur" value="100" size="3"></p>  <p class="ligne"><label for="format">Format (PDF uniquement)</label><select id="format">    <option value="portrait">A4 vertical</option><option value="paysage">A4 horizontal</option><option value="hauteur50">Hauteur 50%</option>  </select>');$("#fenetre > div:last").show();if($("#texte").val().length)$("#texte").attr("data-auto",0);$("#doc").on("change keyup",function(e){if(e.which==13)$("#fenetre a.icon-ok").click();var texte=$("#doc option:selected").text();if($("#texte").attr("data-auto")==1)$("#texte").val(this.value>0?texte.substr(0,texte.lastIndexOf("(")-1):"---");if("pdfjpgpegpng".indexOf(texte.slice(-4,-1))>-1)$("#vue").change().parent().show();else{$("#vue, #largeur, #format").parent().hide();$("#vue").prop("checked",false)}majapercu()});$("#texte").on("change keypress",function(e){if(e.which==0)return;if(e.which==13)$("#fenetre a.icon-ok").click();if(this.value.length==0){$(this).data("auto",1);$("#doc").change()}else{$(this).data("auto",0);majapercu()}});$("#vue").on("change",function(){if($("#vue").is(":checked")){if($("#doc option:selected").text().slice(-4,-1)=="pdf"){$("#largeur, #format").parent().show();$("#texte").parent().hide()}else if("jpgpegpng".indexOf($("#doc option:selected").text().slice(-4,-1))>-1){$("#largeur").parent().show();$("#format, #texte").parent().hide()}}else{$("#texte").parent().show();$("#largeur, #format").parent().hide()}majapercu()});$("#format").on("change keyup",function(e){if(e.which==13)$("#fenetre a.icon-ok").click();majapercu()});$("#largeur").on("keydown",function(e){if(e.which==38)++this.value;else if(e.which==40)--this.value}).on("change keyup",function(e){if(e.which==0)return;if(e.which==13)$("#fenetre a.icon-ok").click();if(this.value!=$(this).data("valeur")){$(this).data("valeur",this.value);majapercu()}}).attr("data-valeur",100);$("#rep").on("change",function(){$("#doc").html(data.docs[this.value]).change()});$("#mat").on("change",function(){$("#rep").html(data.reps[this.value]).change()}).focus().change();$("#fenetre a.icon-ok").on("click",function(){if($("#doc").val()){if($("#vue").is(":checked")&&"pdfjpgpegpng".indexOf($("#doc option:selected").text().slice(-4,-1))>-1)insert(el,$("#apercu").html(),"","");else insert(el,'<a href="download?id='+$("#doc").val()+'">',"</a>",$("#texte").val());$("#fenetre,#fenetre_fond").remove()}});$("#mat option").each(function(){if($("body").attr("data-matiere")==this.value)$("#mat").val(this.value).change()})};if("mats"in data)affichedocs(data)})}function insertion_lien2(el){popup('<a class="icon-ok" title="Valider"></a><h3>Insertion d\'un lien</h3>  <p class="ligne"><label for="texte">Texte visible&nbsp;: </label><input type="text" id="texte" value="'+marqueselection(el)+'" size="80"></p>  <p class="ligne"><label for="url">Adresse&nbsp;: </label><input type="text" id="url" value="http://" size="80"></p>  <hr><h3>Aperçu</h3><div id="apercu" style="text-align:center;"></div>',true);$("#fenetre input").on("click keyup",function(){$("#apercu").html($("#texte").val().length?'<a onclick="return false;" href="'+$("#url").val()+'">'+$("#texte").val()+"</a>":"[Écrivez un texte visible]")}).on("keypress",function(e){if(e.which==13)$("#fenetre a.icon-ok").click()}).first().keyup().focus();$("#fenetre a.icon-ok").on("click",function(){insert(el,'<a href="'+$("#url").val()+'">',"</a>",$("#texte").val());$("#fenetre,#fenetre_fond").remove()});$("#fenetre a.icon-ferme,#fenetre_fond").on("click",function(){marqueselection(el,true)})}function insertion_tex(el){var chargement=typeof MathJax=="undefined"?'<script type="text/javascript" src="/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script><script type="text/x-mathjax-config">MathJax.Hub.Config({tex2jax:{inlineMath:[["$","$"],["\\\\(","\\\\)"]]}});</script>':"";var sel=marqueselection(el);var type="t1";if(sel.length)switch(sel.substring(0,2)){case"\\[":case"$$":type="t2";case"\\(":sel=sel.substring(2,sel.length-2);break;default:sel=sel.trim("$")}popup(chargement+'<a class="icon-montre" title="Mettre à jour l\'aperçu"></a><a class="icon-ok" title="Valider"></a><h3>Insertion de formules LaTeX</h3>  <p>Vous pouvez ci-dessous entrer et modifier une formule LaTeX. L\'aperçu présent en bas sera mis à jour uniquement lorsque vous cliquez sur l\'icône <span class="icon-montre"></span>.</p>  <p class="ligne"><label for="t1">La formule est en ligne (pas de retour)</label><input type="radio" name="type" id="t1" value="1"></p>  <p class="ligne"><label for="t2">La formule est hors ligne (formule centrée)</label><input type="radio" name="type" id="t2" value="2"></p>  <textarea id="formule" rows="3">'+sel+'</textarea>  <hr><h3>Aperçu</h3><div id="apercu" style="text-align:center;">[Demandez l\'aperçu en cliquant sur l\'icône <span class="icon-montre"></span>]</div>',true);$("#"+type).prop("checked",true);$("#formule").focus();$("#fenetre a.icon-montre").on("click",function(){if($("#formule").val().length){$("#apercu").html($("#t1").is(":checked")?"$"+$("#formule").val()+"$":"\\["+$("#formule").val()+"\\]").css("text-align","left");MathJax.Hub.Queue(["Typeset",MathJax.Hub,"apercu"])}else $("#apercu").html("[Écrivez une formule]").css("text-align","center")});$("#fenetre a.icon-ok").on("click",function(){if($("#t1").is(":checked"))insert(el,"$","$",$("#formule").val());else insert(el,"\\[","\\]",$("#formule").val());$("#fenetre,#fenetre_fond").remove()});$("#fenetre a.icon-ferme,#fenetre_fond").on("click",function(){marqueselection(el,true)})}function insertion_par1(el){insert(el,"<p>","</p>")}function insertion_par2(el){insert(el,"<div class='note'>","</div>")}function insertion_par3(el){insert(el,"<div class='annonce'>","</div>")}function insertion_retour(el){insert(el,"<br>","")}function insertion_gras(el){insert(el,"<strong>","</strong>")}function insertion_italique(el){insert(el,"<em>","</em>")}function insertion_souligne(el){insert(el,"<u>","</u>")}function insertion_exp(el){insert(el,"<sup>","</sup>")}function insertion_ind(el){insert(el,"<sub>","</sub>")}function aidetexte(){popup('<h3>Aide et explications</h3>  <p>Il y a deux modes d\'éditions possibles pour éditer un texte&nbsp;: le mode «&nbsp;balises visibles&nbsp;» et le mode «&nbsp;balises invisibles&nbsp;». Il est possible de passer de l\'un à l\'autre&nbsp;:</p>  <ul>    <li><span class="icon-source"></span> permet de passer en mode «&nbsp;balises visibles&nbsp;» (par défaut), où le texte à taper est le code HTML de l\'article. Ce mode est plus précis. Les boutons aux dessus aident à utiliser les bonnes balises.</li>    <li><span class="icon-nosource"></span> permet de passer en mode «&nbsp;balises invisibles&nbsp;», où le texte est tel qu\'il sera affiché sur la partie publique, et modifiable. Ce mode est moins précis, mais permet le copié-collé depuis une page web ou un document Word/LibreOffice.  </ul>  <p>Une fonction de nettoyage du code HTML, permettant d\'assurer une homogénéité et une qualité d\'affichage optimales, est lancée à chaque commutation entre les deux modes, à chaque clic sur un des boutons disponibles, à chaque copie/coupe de texte et à chaque passage à la ligne.</p>  <p>En HTML, toutes les mises en formes sont réalisées par un encadrement de texte entre deux balises&nbsp;: &lt;h3&gt; et &lt;/h3&gt; pour un gros titre, &lt;p&gt; et &lt;/p&gt; pour un paragraphe. Le retour à la ligne simple, qui ne doit exister que très rarement, est une balise simple &lt;br&gt;. Mais les boutons disponibles sont là pour vous permettre de réaliser le formattage que vous souhaitez&nbsp;:</p>  <ul>    <li><span class="icon-titres"></span>&nbsp;: différentes tailles de titres (fenêtre supplémentaire pour choisir)</li>    <li><span class="icon-par1"></span>&nbsp;: paragraphe classique, qui doit obligatoirement encadrer au minimum chaque ligne de texte. Apparaît automatiquement au passage à la ligne si on l\'oublie.</li>    <li><span class="icon-par2"></span>&nbsp;: paragraphe important, écrit en rouge</li>    <li><span class="icon-par3"></span>&nbsp;: paragraphe très important, écrit en rouge et encadré</li>    <li><span class="icon-retour"></span>&nbsp;: retour à la ligne. Identique à un appui sur Entrée, et souvent inutile.</li>    <li><span class="icon-gras"></span>&nbsp;: mise en gras du texte entre les balises</li>    <li><span class="icon-italique"></span>&nbsp;: mise en italique du texte entre les balises</li>    <li><span class="icon-souligne"></span>&nbsp;: soulignement du texte entre les balises</li>    <li><span class="icon-omega"></span>&nbsp;: lettres grecques (fenêtre supplémentaire pour choisir)</li>    <li><span class="icon-sigma"></span>&nbsp;: symboles mathématiques (fenêtre supplémentaire pour choisir)</li>    <li><span class="icon-exp"></span>&nbsp;: mise en exposant du texte entre les balises</li>    <li><span class="icon-ind"></span>&nbsp;: mise en indice du texte entre les balises</li>    <li><span class="icon-ol"></span>&nbsp;: liste numérotée. Une fenêtre supplémentaire permet de choisir le type (1,A,a,I,i) et la première valeur. Les différentes lignes de la liste sont constituées par les balises &lt;li&gt; et &lt;/li&gt;</li>    <li><span class="icon-ul"></span>&nbsp;: liste à puces. Les différentes lignes de la liste sont constituées par les balises &lt;li&gt; et &lt;/li&gt;</li>    <li><span class="icon-lien1"></span>&nbsp;: lien d\'un document disponible ici (fenêtre supplémentaire pour choisir)</li>    <li><span class="icon-lien2"></span>&nbsp;: lien vers un autre site web (fenêtre supplémentaire pour entre l\'adresse)</li>    <li><span class="icon-tex"></span>&nbsp;: insertion de code LaTeX (fenêtre supplémentaire pour le taper)</li>  </ul>  <p class="tex2jax_ignore">Il est possible d\'insérer du code en LaTeX, sur une ligne séparée (balises \\[...\\] ou balises $$...$$) ou au sein d\'une phrase (balises $...$ ou balises \\(...\\)). Il faut ensuite taper du code en LaTeX à l\'intérieur. La prévisualisation est réalisée en direct.</p>',false)
+}function echange(el1,el2){if(el1.length&&el2.length){$("article").css("position","relative");el1.css("opacity",.3);el2.css("opacity",.3);el2.animate({top:el1.position().top-el2.position().top},1e3);el1.animate({top:(el2.outerHeight(true)+el2.outerHeight())/2},1e3,function(){el1.css("opacity",1);el2.css("opacity",1);el1.insertAfter(el2);el1.css({position:"static",top:0});el2.css({position:"static",top:0})})}}function cache(el){var prop=el.parent().attr("data-id").split("|");$.ajax({url:"ajax.php",method:"post",data:{cache:1,action:prop[0],id:prop[1]},dataType:"json",el:el,fonction:function(el){el.parent().addClass("cache");el.removeClass("icon-cache").addClass("icon-montre").off("click").on("click",function(){montre($(this))}).attr("title","Montrer à nouveau")}})}function montre(el){var prop=el.parent().attr("data-id").split("|");$.ajax({url:"ajax.php",method:"post",data:{montre:1,action:prop[0],id:prop[1]},dataType:"json",el:el,fonction:function(el){el.parent().removeClass("cache");el.removeClass("icon-montre").addClass("icon-cache").off("click").on("click",function(){cache($(this))}).attr("title","Cacher à nouveau")}})}function monte(el){var parent=el.parent();var prop=parent.attr("data-id").split("|");$.ajax({url:"ajax.php",method:"post",data:{monte:1,action:prop[0],id:prop[1]},dataType:"json",el:parent,fonction:function(el){if(!el.prev().prev().is("article")){el.children(".icon-monte").hide(1e3);el.prev().children(".icon-monte").show(1e3)}if(!el.next().is("article")){el.children(".icon-descend").show(1e3);el.prev().children(".icon-descend").hide(1e3)}echange(el.prev(),el)}})}function descend(el){var parent=el.parent();var prop=parent.attr("data-id").split("|");$.ajax({url:"ajax.php",method:"post",data:{descend:1,action:prop[0],id:prop[1]},dataType:"json",el:parent,fonction:function(el){if(!el.prev().is("article")){el.children(".icon-monte").show(1e3);el.next().children(".icon-monte").hide(1e3)}if(!el.next().next().is("article")){el.children(".icon-descend").hide(1e3);el.next().children(".icon-descend").show(1e3)}echange(el,el.next())}})}function supprime(el){var parent=el.parent();var prop=parent.data("id").split("|");var item="un élément";switch(prop[0]){case"infos":item="une information";break;case"pages":item="la matière <em>"+$("h3",parent).text()+"</em>. Les informations qui y sont écrites seront aussi supprimées";break;case"reps":item="le répertoire <em>"+$(".nom",parent).map(function(){return this.textContent||$(this).find("input").val()}).get(0)+"</em>. <strong>Tous les sous-répertoires et documents qui s'y trouvent seront aussi supprimés</strong>";break;case"docs":item="le document <em>"+$(".nom",parent).map(function(){return this.textContent||$(this).find("input").val()}).get(0)+"</em>";break;case"colles":item="le programme de colle de la "+$(".edition",parent).text().toLowerCase();break;case"cdt-elems":item="un élément du cahier de texte";break;case"cdt-types":item="le type de séances <em>"+$("h3",parent).text()+"</em>. <strong>Les éléments du cahier de texte associés à ce type seront aussi supprimés</strong>";break;case"cdt-raccourcis":item="le raccourci de séance <em>"+$("h3",parent).text()+"</em>. Aucun élément du cahier de texte ne sera supprimé";break;case"notes":parent=parent.parent();item="une colle ou séance sans note du <em>"+$("td:first",parent).text()+"</em>, d'une durée de "+$("td:eq(3)",parent).text()+". Toutes les notes de cette colle seront supprimées";break;case"matieres":item="la matière <em>"+$("h3",parent).text()+"</em>. <p class=\"note\"><strong>ATTENTION&nbsp;: Les programmes de colles, le cahier de texte et les notes correspondantes seront toutes automatiquement supprimées.</strong></p> <p>Les répertoires, les documents, les pages d'informations spécifiques et les éléments de l'agenda associés à la matière seront conservés mais ne seront plus associés à une matière&nbsp;: ils seront désormais visibles dans le contexte «&nbsp;général&nbsp;».<br><strong>Si vous souhaitez simplement réinitialiser la matière, ce n'est pas la bonne méthode</strong>&nbsp;: vous devriez pouvoir faire ce que vous souhaitez avec les possibilités de cette page";break;case"groupes":item="le groupe <em>"+($(".editable",parent).text()||$("input:first",parent).val())+"</em>. Les utilisateurs concernés ne seront pas supprimés";break;case"agenda-elems":item="un événement de l'agenda";break;case"agenda-types":item="le type d'événement <em>"+$("h3",parent).text()+"</em>. <strong>Les événements de l'agenda associés à ce type seront aussi supprimés</strong>";break}confirmation("Vous allez supprimer XXX.<br>Cette opération n'est pas annulable.".replace("XXX",item),this,function(el){$.ajax({url:"ajax.php",method:"post",data:{supprime:1,action:prop[0],id:prop[1]},dataType:"json",el:parent,fonction:function(el){if(prop[0].match(/^(agenda|colles)$/))location.reload(true);else el.remove()}})})}function lock(el){var parent=el.parent();var prop=parent.data("id").split("|");var protection=el.data("val");popup('<a class="icon-ok" title="Valider ce choix"></a><h3>Accès à l\'information</h3><table id="selmult">  <tr class="categorie"><td>Accès public</td><td><input value="0" type="checkbox"></td></tr>  <tr class="categorie"><td>Utilisateurs identifiés</td><td><input value="6" type="checkbox"></td></tr>  <tr class="element"><td>Invités</td><td><input value="1" type="checkbox"></td></tr>  <tr class="element"><td>Élèves</td><td><input value="2" type="checkbox"></td></tr>  <tr class="element"><td>Colleurs</td><td><input value="3" type="checkbox"></td></tr>  <tr class="element"><td>Administratifs</td><td><input value="4" type="checkbox"></td></tr>  <tr class="element"><td>Professeurs</td><td><input value="5" type="checkbox"></td></tr>  <tr class="categorie"><td>Information invisible</td><td><input value="32" type="checkbox"></td></tr>  </tbody></table>',true);var f=$("#fenetre");if(protection==0||protection==32)$('input[value="'+protection+'"]',f).prop("checked",true).change();else{$("input[value=6]",f).prop("checked",true).change();for(var a=1;a<6;a++)if((protection-1>>a-1&1)==0)$('input[value="'+a+'"]',f).prop("checked",true).change()}var f=$("#fenetre");$("input[value=0],input[value=6],input[value=32]",f).parent().parent().addClass("categorie");$("tr:not(.categorie)",f).addClass("element");$("input",f).on("click",function(){if(this.value==0||this.value==32)$(this).parent().parent().siblings().find("input[type=checkbox]").prop("checked",false).change();else{$("input[value=0],input[value=32]",f).prop("checked",false).change();$("input[value=6]",f).prop("checked",true).change();if(this.value==6)$("tr:not(.categorie) input",f).prop("checked",true).change()}});$("tr",f).on("click",function(e){if(!$(e.target).is("input"))$(this).find("input").click()});$("input",f).on("change",function(){$(this).parent().parent().removeClass("sel");if(this.checked)$(this).parent().parent().addClass("sel")});$(".icon-ok",f).on("click",function(){if($('input[value="32"]',f).prop("checked"))var val=32;else if($('input[value="0"]',f).prop("checked"))var val=0;else var val=32-$("input:checked:not([value=6])",f).map(function(){return this.value|0}).get().reduce(function(acc,v){return acc+Math.pow(2,v-1)},0);el.data("val",val);$.ajax({url:"ajax.php",method:"post",data:{action:prop[0],id:prop[1],champ:"protection",val:val},dataType:"json",el:parent,fonction:function(el){location.reload(true)}})})}function ajoutecolle(el){var article=el.parent();el.before('<a class="icon-annule" title="Annuler"></a><a class="icon-ok" title="Valider"></a>');el.next().addBack().hide();var form=$("<form></form>").appendTo(article).html($("#form-ajoutecolle").html());$("textarea",form).textareahtml();$("input",form).attr("id","cache");$(".icon-annule",article).on("click",function(){$("form,.icon-annule,.icon-ok",article).remove();el.next().addBack().show()});$("a.icon-ok",article).on("click",function(){$("textarea",form).each(function(){this.value=nettoie($(this).is(":visible")?this.value:$(this).next().html())});var id=article.data("id").split("|")[1];$.ajax({url:"ajax.php",method:"post",data:form.serialize()+"&action=ajout-colle&id="+id,dataType:"json",el:article,fonction:function(el){var texte=$("textarea",el).val();var cache=$("input",el).is(":checked");if(cache)el.addClass("cache");el.data("id","colles|"+id);$(".icon-aide",el).nextAll().remove();$(".icon-aide",el).after((cache?'<a class="icon-montre" title="Afficher le programme de colles sur la partie publique"></a>':'<a class="icon-cache" title="Rendre invisible le programme de colles sur la partie publique"></a>')+'<a class="icon-supprime" title="Supprimer ce programme de colles"></a><div class="editable edithtml" data-id="colles|texte|'+id+'" placeholder="Texte du programme de colles">'+texte+"</div>");$("a.icon-cache,a.icon-montre,a.icon-supprime",el).on("click",function(){window[this.className.substring(5)]($(this))});$(".editable",el).editinplace()}})});$("input,select",form).on("keypress",function(e){if(e.which==13){e.preventDefault();$("a.icon-ok",article).click()}})}function valide(){var data="";if($("#planning").length)data="action=planning&"+$("form").serialize();else{var id=$(this).parent().attr("data-id").split("|");data="action="+id[0]+"&id="+id[1]+"&"+$(this).nextAll("form").serialize()}if(data.length)$.ajax({url:"ajax.php",method:"post",data:data,dataType:"json",el:this,fonction:function(el){if(el.classList[1]!="noreload")location.reload(true)}});else affiche("<p>Aucune donnée envoyée.</p>","nok")}function formulaire(){var idform=this.className.split(" ")[0].substring(5);var action=$("#form-"+idform).data("action");$("#epingle").remove();var article=$('<article id="epingle"><a class="icon-ferme" title="Fermer"></a>  <a class="icon-aide" title="Aide pour ce formulaire"></a>  <a class="icon-ok" title="Valider"></a></article>').insertBefore($("article,#calendrier,#parentsdoc+*").first());var form=$("<form></form>").appendTo(article).html($("#form-"+idform).html());$(".edithtml",form).textareahtml();$("input[name], select[name]:not([multiple])",form).attr("id",function(){return this.getAttribute("name")});switch(action){case"reps":$(this).init_reps();break;case"ajout-rep":form.append('<input type="hidden" name="parent" value="'+$(this).parent().data("id").split("|")[1]+'">');break;case"docs":case"ajout-doc":$(this).init_docs(action);break;case"cdt-elems":form.init_cdt_boutons();break;case"ajout-cdt-raccourci":form.init_cdt_raccourcis();break;case"notes":case"ajout-notes":$(this).init_notes(action);break;case"agenda-elems":$(this).init_evenements();break;case"deplcolle":$("#ancien,#nouveau").each(function(){$(this).datetimepicker({format:"d/m/Y Ghi",timepicker:true})});break;case"ajout-utilisateurs":form.init_ajout_utilisateurs();break;case"ajout-groupe":$(".usergrp span",form).on("click",utilisateursgroupe);break}$("select[multiple]",form).each(selmult);$("#epingle .icon-ferme").on("click",function(){$("#epingle").remove()});$("#epingle a.icon-aide").on("click",function(){popup($("#aide-"+idform).html(),false)});$("#epingle a.icon-ok").on("click",function(){$(".edithtml",form).each(function(){this.value=nettoie($(this).is(":visible")?this.value:$(this).next().html())});if(action=="notes"||action=="ajout-notes")$("#epingle select:not(:visible)").val("x");$.ajax({url:"ajax.php",method:"post",data:form.serialize()+"&action="+action,dataType:"json",el:"",fonction:function(el){location.reload(true)}})});$("input,select",form).on("keypress",function(e){if(e.which==13){e.preventDefault();$("#epingle a.icon-ok").click()}})}$.fn.init_reps=function(){var el=$(this);var form=$("#epingle form");var sel=$("select[multiple]",form);var id=el.parent().data("id").split("|")[1];var donnees=el.parent().data("donnees").split("|");var protection=donnees[2];var nom=el.siblings(".nom").text().split(/\/\s/).pop()||el.parent().find("input").val();$("em",form).text(nom);if(protection==0||protection==32)sel.val(protection);else{sel.val(6);for(var a=1;a<6;a++)if((protection-1>>a-1&1)==0)$('option[value="'+a+'"]',sel).prop("selected",true)}if(donnees[0]==0)$("#nom,#parent,#menu",form).parent().remove();else{$("#nom",form).val(nom);if(donnees[1]=="1")$("#menu",form).prop("checked",true);$('[data-parents*=",'+id+',"]',form).prop("disabled",true)}form.append('<input type="hidden" name="id" value="'+id+'">');$('input[type="button"]',form).on("click",function(){var action=this.value.substring(0,4)=="Prop"?"propage":"vide";var contexte=$(this).parent().find("em").text();var texte=action=="propage"?"Vous allez propager le réglage d'accès du répertoire <em>"+contexte+"</em> à l'ensemble de ses sous-répertoires et des documents qu'ils contiennent.<br>Vous pourrez modifier à nouveau le réglage de chaque document ou répertoire, de façon individuelle.":"Vous allez vider le répertoire <em>"+contexte+"</em>. Cela supprimera définitivement l'ensemble de ses sous-répertoires et des documents qu'ils contiennent.<br>Cette opération n'est pas annulable.";confirmation(texte,this,function(el){$.ajax({url:"ajax.php",method:"post",data:"action=reps&id="+id+"&"+action+"=1",dataType:"json",el:"",fonction:function(el){location.reload(true)}})})})};$.fn.init_docs=function(action){var el=$(this);var form=$("#epingle form");var nom=el.siblings(".nom").text().split(/\/\s/).pop()||el.parent().find("input").val();$("em",form).text(nom);var id=el.parent().data("id").split("|")[1];if(action=="docs"){var protection=el.parent().data("protection");form.append('<input type="hidden" name="id" value="'+id+'">');$("#nom",form).val(nom)}else{var protection=el.parent().data("donnees").split("|")[2];$("#fichier",form).on("change",function(){if(!$("#nom",form).val().length){var f=this.value;$("#nom",form).val(f.substring(f.lastIndexOf("\\")+1,f.lastIndexOf("."))||f)}});form.append('<input type="hidden" name="parent" value="'+id+'">')}var sel=$("select[multiple]",form);if(protection==0||protection==32)sel.val(protection);else{sel.val(6);for(var a=1;a<6;a++)if((protection-1>>a-1&1)==0)$('option[value="'+a+'"]',sel).prop("selected",true)}form.append('<input type="hidden" name="action" value="'+action+'">');$("#epingle a.icon-ok").addClass("icon-envoidoc").removeClass("icon-ok").on("click",function(){$.ajax({url:"docs.php",method:"post",data:"connexion=1",dataType:"json",el:"",fonction:function(el){if($("#fichier")[0].files.length>0){window.clearTimeout(extinction);$("#log").html("Envoi du document. Cela peut prendre du temps...")}var data=new FormData(form[0]);$.ajax({url:"ajax.php",method:"post",data:data,dataType:"json",contentType:false,processData:false,el:"",fonction:function(el){location.reload(true)}})}})})};$.fn.init_cdt_boutons=function(){var form=this;$("#jour,#pour").datetimepicker({format:"d/m/Y",timepicker:false});$("#h_debut").datetimepicker({format:"Ghi",datepicker:false,onClose:function(t,input){$("#h_fin").val(function(i,v){return v||(input.val().length?parseInt(input.val().slice(0,-3))+2+input.val().slice(-3):"")})}});$("#h_fin").datetimepicker({format:"Ghi",datepicker:false});var zero=function(n){return String(n).length==1?"0"+n:String(n)};$("#raccourci").on("change keyup",function(){var valeurs=raccourcis[this.value];for(var cle in valeurs){if(cle=="jour"){var t=new Date;var j=parseInt(valeurs["jour"]);t.setDate(j>t.getDay()?t.getDate()-t.getDay()-7+j:t.getDate()-t.getDay()+j);$("#jour").val(zero(t.getDate())+"/"+zero(t.getMonth()+1)+"/"+t.getFullYear())}else $("#"+cle).val(valeurs[cle])}$(this).data("modif",1);$("#tid").change()}).data("modif",0);$("#tid").on("change keyup",function(){switch(parseInt(seances[this.value])){case 0:$("#h_debut,#demigroupe").parent().show();$("#h_fin,#pour").parent().hide();break;case 1:$("#h_debut,#h_fin,#demigroupe").parent().show();$("#pour").parent().hide();break;case 2:$("#h_debut,#h_fin").parent().hide();$("#pour,#demigroupe").parent().show();break;case 3:$("#h_debut,#h_fin,#pour").parent().hide();$("#demigroupe").parent().show();break;default:$("#h_debut,#h_fin,#pour,#demigroupe").parent().hide()}$("#jour").change()});$("input,#demigroupe",form).on("change keyup",function(){if($("#raccourci").data("modif")==0)$("#raccourci").val(0);else $("#raccourci").data("modif",0)});$("input,select",form).on("keypress",function(e){if(e.which==13)$("a.icon-ok",el).click()});$("select:first",form).focus();$("#tid").change()};$.fn.init_cdt_raccourcis=function(){this.each(function(){var form=$(this);$('[id^="h_d"]',form).datetimepicker({format:"Ghi",datepicker:false,onClose:function(t,input){$('[id^="h_f"]',form).val(function(i,v){return v||(input.val().length?parseInt(input.val().slice(0,-3))+2+input.val().slice(-3):"")})}});$('[id^="h_fin"]').datetimepicker({format:"Ghi",datepicker:false});$('[id^="type"]',form).on("change keyup",function(){switch(parseInt(seances[this.value])){case 0:$('[id^="h_d"],[id^="dem"]',form).parent().show();$('[id^="h_f"]',form).parent().hide();break;case 1:$('[id^="h_d"],[id^="h_f"],[id^="dem"]',form).parent().show();break;case 2:case 3:$('[id^="h_d"],[id^="h_f"]',form).parent().hide();$('[id^="dem"]',form).parent().show();break;default:$('[id^="h_d"],[id^="h_f"],[id^="dem"]',form).parent().hide()}}).change();$("input,select",form).on("keypress",function(e){if(e.which==13)$("a.icon-ok",form).click()})})};$.fn.init_notes=function(action){var el=$(this);var form=$("#epingle form").append($("#form-notes").html());var table=$("table",form);$("input, select",form).attr("id",function(){return this.getAttribute("name")});$("tr[data-id]",table).append("<td>"+$("div",form).html()+"</td>");$("select",table).attr("name",function(){return"e"+$(this).parent().parent().data("id")});$("div",form).remove();if($("input:checkbox",table).length){$("tr[data-id]",form).hide();$("input:checkbox",table).on("change",function(){if($("input:checkbox:last",table).prop("checked"))return $("tr[data-id]",form).show();var ids=$("input:checked",table).map(function(){return this.value.split(",")}).get().concat();$("tr[data-id]:not(.orig)",table).hide();for(var i=0;i<ids.length;i++)$('tr[data-id="'+ids[i]+'"]',form).show()})}function marque_dejanotes(sid){if(sid==0)return true;var dn=dejanotesautres[sid].split(",");for(var i=0;i<dn.length;i++)$('tr[data-id="'+dn[i]+'"]',form).addClass("dejanote").find("td:eq(0)").text(function(){return this.textContent+" (noté par un autre colleur)"});var dn=dejanotesperso[sid].split(",");for(var i=0;i<dn.length;i++)$('tr[data-id="'+dn[i]+'"]:not(.orig)',form).addClass("dejanote").find("td:eq(0)").text(function(){return this.textContent+" (déjà noté par vous-même)"});$(".dejanote select").prop("disabled",true).val("x")}$("#jour").datetimepicker({format:"d/m/Y",timepicker:false,onShow:function(){if($("#td").is(":checked"))this.setOptions({minDate:$("#form-ajoute option:eq(1)").data("date"),maxDate:new Date(new Date($("#form-ajoute option:last").data("date").replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z){return z+"-"+y+"-"+x})).getTime()+6*864e5)});else this.setOptions({minDate:debut||$("#sid option:selected").data("date"),maxDate:new Date(new Date((fin||$("#sid option:selected").next().data("date")).replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z){return z+"-"+y+"-"+x})).getTime()-864e5)})}});$("#heure").datetimepicker({format:"Ghi",datepicker:false,defaultTime:"15h30"});$("#duree").datetimepicker({format:"Ghi",datepicker:false,defaultTime:"0h00",step:10}).on("change",function(){$(this).removeClass("auto")});$("select",table).on("change keyup",function(){var nb=$("table select:visible",form).filter(function(){return this.value!="x"}).length;var duree=nb*(dureecolle||20);if($("#duree").is(".auto")||duree>$("#duree").val().replace(/^(\d*)h(\d*)$/,function(tout,x,y){return 60*(x|0)+(y|0)}))$("#duree").val((duree/60|0)+"h"+(duree%60||"")).addClass("auto")});if(action=="ajout-notes"){$("#sid").on("change keyup",function(){$(".dejanote td:first-child").text(function(){return this.textContent.replace(" (noté par un autre colleur)","").replace(" (déjà noté par vous-même)","")});$(".dejanote").removeClass("dejanote").find("select").prop("disabled",false);marque_dejanotes($("#sid").val());var jour=new Date($("#jour").val().replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z){return z+"-"+y+"-"+x}));var debut=new Date($("#sid option:selected").data("date").replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z){return z+"-"+y+"-"+x}));var fin=new Date($("#sid option:selected").next().data("date").replace(/(.{2})\/(.{2})\/(.{4})/,function(tout,x,y,z){return z+"-"+y+"-"+x}));if(jour<debut||jour>fin){debut=debut.toJSON();$("#jour").val(debut.substr(8,2)+"/"+debut.substr(5,2)+"/"+debut.substr(0,4))}}).change();$("#td").on("change keyup",function(){if(this.checked){$("#sid").parent().hide();$("#description").parent().show();table.hide()}else{$("#sid").parent().show();$("#description").parent().hide();table.show()}});$("#description").parent().hide()}else{var tr=el.parent().parent();if(el.data("sid")){$("#description, #td").parent().remove();var sid=el.data("sid");var debut=$('#form-ajoute option[value="'+sid+'"]').data("date");var fin=$('#form-ajoute option[value="'+sid+'"]').next().data("date");var eleves=el.data("eleves").split("|");var notes=el.data("notes").split("|");for(var i=0;i<eleves.length;i++)$('tr[data-id="'+eleves[i]+'"]',form).addClass("orig").show().find("select").val(notes[i]).on("change",function(){$(this).parent().parent().removeClass("orig")});$("h3",form).text("Modifier des notes - semaine du "+$('select[name="sid"] option[value="'+sid+'"]').text().split(" ").slice(0,3).join(" "));if(el.next().length)marque_dejanotes(sid);else{$('tr:not(.orig), .orig option[value="x"]',table).remove();$("#duree").prop("disabled",true);form.append("<p>Cette colle a déjà été relevée&nbsp;: il est impossible de modifier quels élèves ont été interrogés ou la durée de la colle. Vous pouvez corriger la date et l'heure (dans la limite de la semaine enregistrée) ou les notes que vous avez mises vous pouvez mettre une note à un élève initialement absent qui a rattrapé sa colle.</p>")}}else{table.remove();$("#td").prop("checked",true).prop("disabled",true);$("#description").val(el.parent().prev().prev().prev().text());$("h3",form).text("Modifier la séance de TD sans note");if(el.next().length==0){$("#duree").prop("disabled",true);form.append("<p>Cette séance a déjà été relevée&nbsp;: il est impossible de modifier sa durée. Vous pouvez corriger la date, l'heure ou la description.</p>")}}$("#id").val(el.parent().data("id").split("|")[1]);$("#jour").val($("td:eq(0)",tr).text().replace(/(.{6})(.{2})/,function(tout,x,y){return x+"20"+y}));$("#heure").val($("td:eq(1)",tr).text().replace("-",""));$("#duree").val($("td:eq(3)",tr).text())}};$.fn.init_ajout_utilisateurs=function(){$("#autorisation,#saisie").on("change",function(){var f=$("#epingle form");var a=$("#autorisation",f).val();if(a==0){$(".affichesiinvite,.affichesiinvitation,.affichesimotdepasse,.mailenvoi,.mailliste",f).hide(0);$("textarea",f).prop("disabled",true).attr("placeholder","Zone de saisie des utilisateurs\nSélectionnez d'abord un type d'utilisateur")}else{var inv=a==1;var mdp=$("#saisie",f).val()==2;$("#saisie",f).parent().toggle(!inv);$(".affichesiinvite",f).toggle(inv);$(".affichesiinvitation",f).toggle(!inv&&!mdp);$(".affichesimotdepasse",f).toggle(!inv&&mdp);$(".mailenvoi",f).toggle(!inv);$(".mailliste",f).toggle(a>2);$("#mailenvoi",f).prop("disabled",mdp).change();$("textarea",f).prop("disabled",false).attr("placeholder",function(){if(inv)return"identifiant_1,motdepasse_1\nidentifiant_2,motdepasse_2\nidentifiant_3,motdepasse_3\n...";else if(mdp)return"nom_1,prénom_1,motdepasse_1\nnom_2,prénom_2,motdepasse_2\nnom_3,prénom_3,motdepasse_3\n...";else return"nom_1,prénom_1,adresse_1\nnom_2,prénom_2,adresse_2\nnom_3,prénom_3,adresse_3\n..."})}}).change();$("#epingle #mailenvoi").on("change",function(){$("#epingle #mailliste").attr("disabled",!this.checked||this.disabled)}).change()};$.fn.init_evenements=function(){var el=$(this);var form=$("#epingle form");$("textarea",form).attr("id","texte");if(el.is(".modifevnmt")){var id=el.attr("id").substr(1);var valeurs=evenements[id];var cles=["type","matiere","debut","fin","texte"];for(var i=0;i<6;i++){$("#"+cles[i]).val(valeurs[cles[i]])}$("#id").val(id);$("#texte").change();$("#jours").prop("checked",valeurs["je"]);$('<a class="icon-supprime" title="Supprimer cette information"></a>').insertBefore($(".icon-ok")).on("click",function(){supprime($(this))}).parent().data("id","agenda-elems|"+id)}$("#debut").datetimepicker({onShow:function(){this.setOptions({maxDate:$("#fin").val()||false})},onClose:function(t,input){$("#fin").val(function(i,v){return v||input.val()})}});$("#fin").datetimepicker({onShow:function(){this.setOptions({minDate:$("#debut").val()||false})},onClose:function(t,input){$("#debut").val(function(i,v){return v||input.val()})}});$("#jours").on("change",function(){var v;if(this.checked){$("#debut,#fin").each(function(){v=this.value.split(" ");$(this).val(v[0]).attr("data-heure",v[1]).datetimepicker({format:"d/m/Y",timepicker:false})})}else{$("#debut,#fin").each(function(){if(this.hasAttribute("data-heure"))$(this).val(this.value+" "+$(this).attr("data-heure")).removeAttr("data-heure");$(this).datetimepicker({format:"d/m/Y Ghi",timepicker:true})})}}).change()};function selmult(){var sel=$(this);var isacces=this.getAttribute("name").indexOf("protection")+1?1:0;function majselect(sel){sel.prev().children().prop("selected",false).text(function(){var options=$(isacces?"option:selected:not([value=6])":"option:selected",sel);if(isacces&&options.length==5)return"Tout utilisateur identifié";if(options.length==0)return"Choisir ...";else return options.map(function(){return this.textContent}).get().join(", ")}).prop("selected",true)}$("<select id="+sel.prev().attr("for")+"><option selected hidden></select>").insertBefore(sel.hide(0)).attr("disabled",sel.attr("disabled")).on("click",function(e){e.preventDefault();this.blur();popup('<a class="icon-ok" title="Valider ce choix"></a><h3>'+sel.prev().prev().text().replace(":","")+'</h3><table id="selmult">'+$("option",sel).map(function(){return"<tr"+(this.selected?' class="sel"':"")+"><td>"+this.textContent+'</td><td><input type="checkbox" '+(this.selected?"checked ":"")+'value="'+this.value+'"></td></tr>'}).get().join("")+"</table>",true);var f=$("#fenetre");if(isacces){$("input[value=0],input[value=6],input[value=32]",f).parent().parent().addClass("categorie");$("tr:not(.categorie)",f).addClass("element");$("input",f).on("click",function(){if(this.value==0||this.value==32)$(this).parent().parent().siblings().find("input[type=checkbox]").prop("checked",false).change();else{$("input[value=0],input[value=32]",f).prop("checked",false).change();$("input[value=6]",f).prop("checked",true).change();if(this.value==6)$("tr:not(.categorie) input",f).prop("checked",true).change()}})}else{$("#selmult",f).prepend('<tr class="categorie"><th></th><th><a class="icon-cocher"></a></th></tr>');$(".icon-cocher",f).on("click",cocher_utilisateurs)}$("tr",f).on("click",function(e){if(!$(e.target).is("input"))$(this).find("input").click()});$("input",f).on("change",function(){$(this).parent().parent().removeClass("sel");if(this.checked)$(this).parent().parent().addClass("sel")});$(".icon-ok",f).on("click",function(){sel.val($("input:checked",f).map(function(){return this.value}).get());majselect(sel);$("#fenetre, #fenetre_fond").remove()})});majselect(sel)}function cocher_utilisateurs(){$(this).toggleClass("icon-cocher icon-decocher").parent().parent().nextUntil(".categorie").find("input").prop("checked",$(this).hasClass("icon-decocher")).change()}function init_utilisateurs(){$(".icones.mailenvoi").each(function(){this.innerHTML=this.textContent==1?'<a class="icon-ok" title="Supprimer la possibilité d\'envoyer des courriels"></a>':'<a class="icon-nok" title="Accorder la possibilité d\'envoyer des courriels"></a>'});$(".mailenvoi a").on("click",mail_utilisateur);$("th .icon-mail").on("click",mail_utilisateurs);$(".icon-cocher").on("click",cocher_utilisateurs);$("td .icon-edite").on("click",edite_utilisateur);$("td .icon-desactive, td .icon-active, td .icon-supprutilisateur, td .icon-validutilisateur").on("click",modif_utilisateur);$("th .icon-desactive, th .icon-active, th .icon-supprutilisateur, th .icon-validutilisateur").on("click",modif_utilisateurs);$("td:not(.icones)").on("click",function(e){$(this).parent().find("input").click()});$("#utilisateurs input").on("change",function(){$(this).parent().parent().removeClass("sel");if(this.checked)$(this).parent().parent().addClass("sel")});function mail_utilisateur(){var val=$(this).hasClass("icon-ok");$.ajax({url:"ajax.php",method:"post",data:{action:"utilisateur",modif:"mailenvoi",id:$(this).parent().parent().data("id"),val:1-val},dataType:"json",el:$(this),fonction:function(el){el.toggleClass("icon-ok icon-nok").attr("title",(val?"Accorder":"Supprimer")+" la possibilité d'envoyer des courriels")}})}function edite_utilisateur(){var id=$(this).parent().parent().data("id");$.ajax({url:"recup.php",method:"post",data:{action:"prefs",id:id},dataType:"json",afficheform:function(data){if("nom"in data){popup($("#form-edite").html(),true);var f=$("#fenetre");$("input[name]",f).attr("id",function(){return this.getAttribute("name")});if(data["valide"])$("#comptedesactive, #demande, #invitation",f).remove();else if(data["demande"])$("#compteactif, #comptedesactive, #invitation",f).remove();else if(data["invitation"])$("#compteactif, #comptedesactive, #demande",f).remove();else $("#compteactif, #demande, #invitation",f).remove();if(data["autorisation"]==2)$("#mailliste",f).parent().remove();else if(data["autorisation"]==1)$("#mailenvoi, #mailexp, #mailcopie, #mailliste",f).parent().remove();$("p:first",f).html(function(i,code){return code.replace("XXX",data["prenom"].length?"de <em>"+data["prenom"]+" "+data["nom"]+"</em>":"<em>"+data["login"]+"</em>").replace("YYY","<em>"+["Invité","Élève","Colleur","Administratif","Professeur"][data["autorisation"]-1]+"</em>")});$('input[type="text"],input[type="email"]',f).val(function(){return data[this.id]});$('input[type="checkbox"]',f).prop("checked",function(){return data[this.id]});$("#mailenvoi",f).on("click",function(){$("#mailexp, #mailcopie, #mailliste",f).prop("disabled",!this.checked);if(this.checked&&!$("#mailexp",f).val())$("#mailexp",f).val(data["prenom"]+" "+data["nom"])});$("#mailexp, #mailcopie, #mailliste",f).prop("disabled",!$("#mailenvoi",f).prop("checked"));$("a.icon-ok",f).on("click",function(){$.ajax({url:"ajax.php",method:"post",data:"action=utilisateur&modif=prefs&id="+id+"&"+$("form",f).serialize(),dataType:"json",el:"",fonction:function(el){location.reload(true)}})});$("input",f).on("keypress",function(e){if(e.which==13){e.preventDefault();$("a.icon-ok",f).click()}})}}})}function modif_utilisateur(){var question="";var compte=$(this).parent().siblings().first().text();compte=compte.length?"de <em>"+compte+"</em>":"d'identifiant <em>"+$(this).parent().siblings().first().next().text()+"</em>";var categorie=$(this).parent().parent().prevUntil(".categorie").last().prev().text().split(" ")[0];switch(this.className.substring(5)){case"desactive":if(categorie=="Invités")question="Vous allez désactiver le compte invité "+compte+". Cela signifie que le compte ne sera pas supprimé mais sera non utilisable pour une connexion. Les associations éventuelles avec les matières seront conservées. Ce compte sera listé dans la partie inférieure du tableau.";else question="Vous allez désactiver le compte "+compte+". Cela signifie que le compte sera toujours visible pour les professeurs mais que l'utilisateur correspondant ne pourra plus se connecter. <strong>Les notes de colles éventuelles seront conservées. Les données associées au compte seront conservées.</strong><br> Les accès spécifiques éventuels pourront être rétablis en réactivant le compte.<br> Ce compte sera listé dans la partie inférieure du tableau.<br> Cette possibilité est particulièrement utile pour un élève ou un colleur parti en cours d'année et dont il faut conserver les notes de colles.";
+break;case"active":if(categorie=="Invités")question="Vous allez réactiver le compte invité "+compte+". La connexion sera à nouveau possible. Ce compte apparaîtra à nouveau dans la partie principale du tableau.";else question="Vous allez réactiver le compte "+compte+". Cela signifie que l'utilisateur correspondant pourra à nouveau se connecter. Il retrouvera son compte, ses notes de colles éventuelles, ses préférences, ses accès spécifiques éventuels, sans modification. Ce compte apparaîtra à nouveau dans la partie principale du tableau.";break;case"supprutilisateur":if(categorie=="Demandes")question="Vous allez supprimer la demande "+compte+". Cela signifie que cette demande ne conduira pas à une création de compte. Le demandeur ne sera pas prévenu de votre décision.<br> Une fois réalisée, cette opération est définitive, mais rien n'empêche le demandeur d'effectuer une nouvelle demande.<br> <strong>Si vous n'attendez plus de nouvelle demande de création de compte, il est certainement préférable de supprimer cette possibilité à l'aide du réglage accessible en cliquant sur l'icône <span class=\"icon-prefs\"></span> en haut à droite sur cette page</strong>";else if(categorie=="Invitations"){var textecolles=$(this).parent().prev().prev().text()=="Élève"?'<p class="note"><strong>ATTENTION : toutes les notes de colles qui ont déjà pu être déclarées sur ce compte seront supprimées. Cette suppression est définitive.</strong></p><p>':"<br>";question="Vous allez supprimer l'invitation "+compte+". Cela signifie que cette invitation ne sera plus valable et que si la personne invitée clique sur le lien reçu par courriel, une erreur apparaîtra devant elle."+textecolles+"<strong>L'invitation envoyée n'a pas de date de péremption&nbsp;: il est n'est pas normal de supprimer l'invitation pour la refaire, à moins de s'être trompé d'adresse électronique. Si la personne invitée vous dit ne pas réussir à s'identifier, proposez-lui de passer par le lien <em>Mot de passe oublié</em>.</strong><br> La personne invitée ne sera pas prévenue de votre décision."}else if(categorie=="Professeurs")question="Vous allez supprimer le compte professeur "+compte+'. <strong>Cela signifie que toutes les préférences de ce compte seront perdues, ainsi que les éventuelles notes de colles.</strong> <p class="note"><strong>Supprimer un compte pour le recréer n\'est pas la bonne méthode pour réinitialiser un compte,</strong></p><p> par exemple si l\'utilisateur du compte vous indique ne pas arriver à se connecter. Dans ce cas, proposez-lui de passer par le lien <em>Mot de passe oublié</em>. Vous pouvez modifier sur la <a href="utilisateurs">gestion des utilisateurs</a> les nom, prénom, identifiant de connexion et adresse électronique de chaque utilisateur.<br> Pour conserver les données de l\'utilisateur mais lui empêcher la connexion, vous pouvez désactiver le compte en cliquant sur <span class="icon-desactive"></span>.<br> Les données des matières auxquelles il est associé sont indépendantes&nbsp;: elles ne seront pas supprimées.';else if(categorie=="Administratifs")question="Vous allez supprimer le compte administratif "+compte+". Cela signifie que toutes les préférences de ce compte seront perdues.";else if(categorie=="Colleurs")question="Vous allez supprimer le compte colleur "+compte+'. <strong>Cela signifie que toutes les préférences de ce compte seront perdues, ainsi que les éventuelles notes de colles.</strong> <p class="note"><strong>Supprimer un compte pour le recréer n\'est pas la bonne méthode pour réinitialiser un compte,</strong></p><p> par exemple si l\'utilisateur du compte vous indique ne pas arriver à se connecter. Dans ce cas, proposez-lui de passer par le lien <em>Mot de passe oublié</em>. Vous pouvez modifier sur la <a href="utilisateurs">gestion des utilisateurs</a> les nom, prénom, identifiant de connexion et adresse électronique de chaque utilisateur.<br> Pour conserver les données de l\'utilisateur mais lui empêcher la connexion, vous pouvez désactiver le compte en cliquant sur <span class="icon-desactive"></span>.';else if(categorie=="Élèves")question="Vous allez supprimer le compte élève "+compte+'. <strong>Cela signifie que toutes les données correspondant à ce compte seront perdues. Les groupes où il apparaît seront modifiés, les notes de colles éventuelles seront supprimées.</strong> <p class="note"><strong>ATTENTION : toutes les notes de colles qui ont déjà pu être déclarées sur ce compte seront supprimées. Cette suppression est définitive.<br> Supprimer un compte pour le recréer n\'est pas la bonne méthode pour réinitialiser un compte,</strong></p><p> par exemple si l\'utilisateur du compte vous indique ne pas arriver à se connecter. Dans ce cas, proposez-lui de passer par le lien <em>Mot de passe oublié</em>. Vous pouvez modifier sur la <a href="utilisateurs">gestion des utilisateurs</a> les nom, prénom, identifiant de connexion et adresse électronique de chaque utilisateur.<br> Pour conserver les données de l\'utilisateur mais lui empêcher la connexion, vous pouvez désactiver le compte en cliquant sur <span class="icon-desactive"></span>.';else if(categorie=="Invités")question="Vous allez supprimer le compte invité "+compte+". Cela signifie que la connexion par ce compte ne sera plus possible.";else question="Vous allez supprimer le compte "+compte+" déjà désactivé. <strong>Cela signifie que toutes les données correspondant à ce compte seront perdues définitivement. Les groupes où il apparaît seront modifiés, les notes de colles éventuelles seront supprimées.</strong>";if(categorie!="Demandes")question=question+"<br>Une fois réalisée, cette opération est définitive.";break;case"validutilisateur":question="Vous allez valider la demande "+compte+". Son compte sera immédiatement actif et un courriel va immédiatement être envoyé pour le/la prévenir.<br> Il sera automatiquement associé à toutes les matières&nbsp;: <strong>pensez à aller supprimer les matières qui ne le concernent pas sur la page de gestion des associations utilisateurs-matières.</strong>"}confirmation(question,this,function(el){$.ajax({url:"ajax.php",method:"post",data:{action:"utilisateur",modif:el.className.substring(5),id:$(el).parent().parent().data("id")},dataType:"json",el:"",fonction:function(){location.reload(true)}})})}function mail_utilisateurs(){var cases=$(this).parent().parent().nextUntil(".categorie").find(":checked");if(cases.length==0){affiche("<p>Aucune case n'est cochée, aucune action ne peut être réalisée.</p>","nok");return}var ids=cases.map(function(){return $(this).parent().parent().data("id")}).get().join(",");var tds=cases.parent().prev().prev();var val=tds.find(".icon-ok").length>=tds.find(".icon-nok").length?0:1;$.ajax({url:"ajax.php",method:"post",data:{action:"utilisateurs",modif:"mailenvoi",ids:ids,val:val},dataType:"json",el:"",fonction:function(){location.reload(true)}})}function modif_utilisateurs(){var cases=$(this).parent().parent().nextUntil(".categorie").find(":checked");if(cases.length==0){affiche("<p>Aucune case n'est cochée, aucune action ne peut être réalisée.</p>","nok");return}var ids=cases.map(function(){return $(this).parent().parent().data("id")}).get().join(",");var comptes=cases.map(function(){var compte=$(this).parent().siblings().first().text();return compte.length?"<em>"+compte+"</em>":"<em>"+$(this).parent().siblings().first().next().text()+"</em>"}).get().join(", ");var pos=comptes.lastIndexOf(",");if(pos>0)comptes=comptes.substring(0,pos)+" et"+comptes.substring(pos+1);var question="";var categorie=$(this).parent().parent().prev().children().text().split(" ")[0];switch(this.className.substring(5)){case"desactive":if(categorie=="Invités")question="Vous allez désactiver les comptes invités "+comptes+". Cela signifie que ces compte ne seront pas supprimés mais seront non utilisables pour une connexion. Les associations éventuelles avec les matières seront conservées. Ces comptes seront listés dans la partie inférieure du tableau.";else question="Vous allez désactiver le compte "+compte+". Cela signifie que le compte sera toujours visible pour les professeurs mais que l'utilisateur correspondant ne pourra plus se connecter. <strong>Les notes de colles éventuelles seront conservées. Les données associées au compte seront conservées.</strong><br> Les accès spécifiques éventuels pourront être rétablis en réactivant le compte.<br> Ce compte sera listé dans la partie inférieure du tableau.<br> Cette possibilité est particulièrement utile pour un élève ou un colleur parti en cours d'année dont il faut conserver les notes de colles.";question="Vous allez désactiver les comptes de "+comptes+". Cela signifie que ces comptes seront toujours visibles pour les professeurs mais que les utilisateurs correspondant ne pourront plus se connecter. <strong>Les notes de colles éventuelles seront conservées. Les données associées aux comptes seront conservées.</strong><br> Les accès spécifiques éventuels pourront être rétablis en réactivant les comptes.<br> Ces comptes seront listés dans la partie inférieure du tableau.<br> Cette possibilité est particulièrement utile pour des élèves ou des colleurs partis en cours d'année et dont il faut conserver les notes de colles.";break;case"active":if(categorie=="Invités")question="Vous allez réactiver les comptes invité "+comptes+". La connexion sera à nouveau possible. Ces comptes apparaîtront à nouveau dans la partie principale du tableau.";else question="Vous allez réactiver les comptes de "+comptes+". Cela signifie que les utilisateurs correspondant pourront à nouveau se connecter. Ils retrouveront leur compte, leurs notes de colles éventuelles, leurs préférences, leurs accès spécifiques éventuels, sans modification. Ces comptes apparaîtront à nouveau dans la partie principale du tableau.";break;case"supprutilisateur":if(categorie=="Demandes")question="Vous allez supprimer les demandes de "+comptes+". Cela signifie que ces demandes ne conduiront pas à des créations de compte. Les demandeurs ne seront pas prévenus de votre décision.<br> Une fois réalisée, cette opération est définitive, mais rien n'empêche les demandeurs d'effectuer une nouvelle demande.<br> <strong>Si vous n'attendez plus de nouvelle demande de création de compte, il est certainement préférable de supprimer cette possibilité à l'aide du réglage accessible en cliquant sur l'icône <span class=\"icon-prefs\"></span> en haut à droite sur cette page</strong>";else if(categorie=="Invitations"){question="Vous allez supprimer les invitations de "+comptes+". Cela signifie que ces invitations ne seront plus valables et que si les personnes invitées cliquent sur le lien reçu par courriel, une erreur apparaîtra devant elles. <p class=\"note\"><strong>ATTENTION : toutes les notes de colles qui ont déjà pu être déclarées sur les comptes de types élèves seront supprimées. Ces suppressions sont définitives.</strong></p> <p><strong>Ces invitations envoyées n'ont pas de date de péremption&nbsp;: il n'est pas normal de supprimer une invitation pour la refaire, à moins de s'être trompé d'adresse électronique. Si une personne invitée vous dit ne pas réussir à s'identifier, proposez-lui de passer par le lien <em>Mot de passe oublié</em>.</strong><br> Les personnes invitées ne seront pas prévenues de votre décision."}else if(categorie=="Professeurs")question="Vous allez supprimer les comptes professeurs de "+comptes+'. <strong>Cela signifie que toutes les préférences de ces comptes seront perdues, ainsi que les éventuelles notes de colles.</strong> <p class="note"><strong>Supprimer un compte pour le recréer n\'est pas la bonne méthode pour réinitialiser un compte,</strong></p><p> par exemple si l\'utilisateur d\'un compte vous indique ne pas arriver à se connecter. Dans ce cas, proposez-lui de passer par le lien <em>Mot de passe oublié</em>. Vous pouvez modifier sur la <a href="utilisateurs">gestion des utilisateurs</a> les nom, prénom, identifiant de connexion et adresse électronique de chaque utilisateur.<br> Pour conserver les données d\'un utilisateur mais lui empêcher la connexion, vous pouvez désactiver le compte en cliquant sur <span class="icon-desactive"></span>.<br> Les données des matières auxquelles ces utilisateurs sont associés sont indépendantes&nbsp;: elles ne seront pas supprimées.';else if(categorie=="Administratifs")question="Vous allez supprimer les comptes administratifs de "+comptes+". Cela signifie que toutes les préférences de ces comptes seront perdues.";else if(categorie=="Colleurs")question="Vous allez supprimer les comptes colleurs de "+comptes+'. <strong>Cela signifie que toutes les préférences de ces comptes seront perdues, ainsi que les éventuelles notes de colles.</strong> <p class="note"><strong>Supprimer un compte pour le recréer n\'est pas la bonne méthode pour réinitialiser un compte,</strong></p><p> par exemple si l\'utilisateur d\'un compte vous indique ne pas arriver à se connecter. Dans ce cas, proposez-lui de passer par le lien <em>Mot de passe oublié</em>. Vous pouvez modifier sur la <a href="utilisateurs">gestion des utilisateurs</a> les nom, prénom, identifiant de connexion et adresse électronique de chaque utilisateur.<br> Pour conserver les données d\'un utilisateur mais lui empêcher la connexion, vous pouvez désactiver le compte en cliquant sur <span class="icon-desactive"></span>.';else if(categorie=="Élèves")question="Vous allez supprimer les comptes élèves de "+comptes+'. <strong>Cela signifie que toutes les données correspondant à ces comptes seront perdues. Les groupes où ils apparaissent seront modifiés, les notes de colles éventuelles seront supprimées.</strong> <p class="note"><strong>ATTENTION : toutes les notes de colles qui ont déjà pu être déclarées sur ces compte seront supprimées. Cette suppression est définitive.<br> Supprimer un compte pour le recréer n\'est pas la bonne méthode pour réinitialiser un compte,</strong></p><p> par exemple si l\'utilisateur d\'un compte vous indique ne pas arriver à se connecter. Dans ce cas, proposez-lui de passer par le lien <em>Mot de passe oublié</em>. Vous pouvez modifier sur la <a href="utilisateurs">gestion des utilisateurs</a> les nom, prénom, identifiant de connexion et adresse électronique de chaque utilisateur.<br> Pour conserver les données d\'un utilisateur mais lui empêcher la connexion, vous pouvez désactiver le compte en cliquant sur <span class="icon-desactive"></span>.';else if(categorie=="Invités")question="Vous allez supprimer les comptes invités de "+comptes+". Cela signifie que la connexion par ces comptes ne sera plus possible.";else question="Vous allez supprimer les comptes de "+comptes+" déjà désactivés. <strong>Cela signifie que toutes les données correspondant à ces comptes seront perdues définitivement. Les groupes où ils apparaîssent seront modifiés, les notes de colles éventuelles seront supprimées. Dans le cas des comptes professeurs, les données des matières associées ne seront pas supprimées.</strong>";if(categorie!="Demandes")question=question+"<br>Une fois réalisée, cette opération est définitive.";break;case"validutilisateur":question="Vous allez valider les demandes de "+comptes+". Leurs comptes seront immédiatement actifs et un courriel va immédiatement leur être envoyé pour les prévenir.<br> Ils seront automatiquement associés à toutes les matières&nbsp;: <strong>pensez à aller supprimer les matières qui ne les concernent pas sur la page de gestion des associations utilisateurs-matières.</strong>"}confirmation(question,this,function(el){$.ajax({url:"ajax.php",method:"post",data:{action:"utilisateurs",modif:el.className.substring(5),ids:ids},dataType:"json",el:"",fonction:function(){location.reload(true)}})})}}function init_utilisateurs_matieres(){$("tbody tr:not(.categorie) td:not(:first-child,:last-child)").each(function(){var valeurs=this.textContent.split("|");this.innerHTML=valeurs[1]==1?'<a class="icon-ok" data-id="'+valeurs[0]+'" title="Supprimer l\'association à la matière"></a>':'<a class="icon-nok" data-id="'+valeurs[0]+'" title="Établir l\'association à la matière"></a>'});$("tbody tr:not(.categorie) a").on("click",association_um);$(".categorie [data-id]").on("click",association_ums).hide(0);$(".icon-cocher").on("click",cocher_utilisateurs).on("click",majicones);$('input[type="checkbox"]').on("click",majicones).on("change",function(){$(this).parent().parent().removeClass("sel");if(this.checked)$(this).parent().parent().addClass("sel")});$("td:first-child").on("click",function(){$(this).parent().find("input").click()});function majicones(){var tr=$(this).parent().parent();if(!tr.hasClass("categorie"))tr=tr.prevAll(".categorie").first();var cases=tr.nextUntil(".categorie").find(":checked");if(cases.length==0){$("[data-id]",tr).hide(0);return}$("[data-id]",tr).each(function(){var avant=$(this).hasClass("icon-ok");var apres=cases.parent().prevAll().find('.icon-ok[data-id="'+this.getAttribute("data-id")+'"]').length<cases.length/2;if(avant!=apres)$(this).toggleClass("icon-ok icon-nok").attr("title",(apres?"Établir":"Supprimer")+" l'association à la matière de tous les cochés")}).show(0)}function association_um(){var val=$(this).hasClass("icon-ok");$.ajax({url:"ajax.php",method:"post",data:{action:"utilisateur-matiere",id:$(this).parent().parent().data("id"),matiere:$(this).data("id"),val:1-val},dataType:"json",el:$(this),fonction:function(el){el.toggleClass("icon-ok icon-nok").attr("title",(val?"Établir":"Supprimer")+" l'association à la matière")}})}function association_ums(){var cases=$(this).parent().parent().nextUntil(".categorie").find(":checked");if(cases.length==0){affiche("<p>Aucune case n'est cochée, aucune action ne peut être réalisée.</p>","nok");return}var ids=cases.map(function(){return $(this).parent().parent().data("id")}).get().join(",");var comptes=cases.map(function(){return $(this).parent().siblings().first().text().split("(")[0].trim()}).get().join(", ");var pos=comptes.lastIndexOf(",");if(pos>0)comptes=comptes.substring(0,pos)+" et"+comptes.substring(pos+1);var val=$(this).hasClass("icon-ok");var mid=this.getAttribute("data-id");var question=val?"Vous allez établir l'association à la matière "+$("#m"+mid).text()+" pour les comptes de "+comptes+". Cela signifie que ces utilisateurs auront accès aux ressources liées à cette matière, en fonction de l'autorisation que vous avez fixée pour ces ressources.":"Vous allez supprimer l'association à la matière "+$("#m"+mid).text()+" pour les comptes de "+comptes+". Cela signifie que ces utilisateurs n'auront plus accès aux ressources liées à cette matière. Si des notes de colles ont été saisies, elles seront automatiquement et définitivement supprimées de la base.";confirmation(question,this,function(el){$.ajax({url:"ajax.php",method:"post",data:{action:"utilisateurs-matieres",ids:ids,matiere:mid,val:val|0},dataType:"json",el:"",fonction:function(el){location.reload(true)}})})}}function init_utilisateurs_groupes(){$('article input[type="checkbox"]').on("change",function(){$.ajax({url:"ajax.php",method:"post",data:{action:"groupes",champ:this.id.substr(0,5),id:this.id.substr(5),val:this.checked|0},dataType:"json",el:"",fonction:function(el){return true}})});$(".usergrp span").append('&nbsp;<a class="icon-edite" title="Éditer les utilisateurs de ce groupe"></a>').on("click",utilisateursgroupe)}function utilisateursgroupe(){popup($("#form-utilisateurs").html(),true);var f=$("#fenetre");var span=$(this);article=span.parent().parent();$("table",f).attr("id","utilisateurs");$("h3",f).append($(".editable",article).text()||$("input:first",article).val());$(".icon-deplie",f).on("click",plie);$(".icon-cocher",f).on("click",cocher_utilisateurs);$("tr:not(.categorie)",f).on("click",function(e){if(!$(e.target).is("input"))$(this).find("input").click()});$("input",f).on("change",function(){$(this).parent().parent().removeClass("sel");if(this.checked)$(this).parent().parent().addClass("sel")});var ids=span.data("uids");$("#u"+ids.replace(/,/g,",#u"),f).prop("checked",true).change();$(".icon-ok",f).on("click",function(){var ids=$("input:checked",f).map(function(){return this.id.replace("u","")}).get().join(",");var noms=$("input:checked",f).parent().prev().map(function(){return this.textContent.split("(")[0].trim()}).get().join(", ")||"[Personne]";if(article.is("div")){$("#uids",article).val(ids);span.data("uids",ids);span.html(noms+'&nbsp;<a class="icon-edite" title="Éditer les utilisateurs de ce groupe"></a>');$("#fenetre, #fenetre_fond").remove()}else $.ajax({url:"ajax.php",method:"post",data:{action:"groupes",champ:"utilisateurs",id:article.data("id").split("|")[1],uids:ids},dataType:"json",el:span,fonction:function(el){el.data("uids",ids);el.html(noms+'&nbsp;<a class="icon-edite" title="Éditer les utilisateurs de ce groupe"></a>');$("#fenetre, #fenetre_fond").remove()}})})}function suppressionmultiple(){var prop=$(this).data("id").split("|");var contexte=$(this).parent().find("h3").text();var item="";switch(prop[2]){case"infos":item="toutes les informations de la page <em>"+contexte+"</em>";break;case"colles":item="tous les programmes de colles de la matière <em>"+contexte+"</em>";break;case"cdt":item="tout le contenu du cahier de texte de la matière <em>"+contexte+"</em>";break;case"docs":item="tous les répertoires et documents de la matière <em>"+contexte+"</em>";break;case"notes":item="toutes les notes de la matière <em>"+contexte+"</em>";break}confirmation("Vous allez supprimer XXX.<br>Cette opération n'est pas annulable.".replace("XXX",item),this,function(el){$.ajax({url:"ajax.php",method:"post",data:"action="+prop[0]+"&id="+prop[1]+"&supprime_"+prop[2]+"=1",dataType:"json",el:$(el),fonction:function(el){el.remove()}})})}function destinatairesmail(){popup($("#form-destinataires").html(),true);var f=$("#fenetre");$("table",f).attr("id","utilisateurs");$(".icon-deplie",f).on("click",plie);$("tr:not(.gr) input.dest",f).attr("id",function(){return"u"+this.value});$("tr:not(.categorie) td:nth-child(-n+2)",f).on("click",function(e){if(!$(e.target).is("input"))$(this).parent().find("input:first").click()});$("input",f).on("change",function(){var tr=$(this).parent().parent().removeClass("sel");if(this.checked)tr.find("input:not(."+this.className+")").prop("checked",false);if(tr.find("input:checked").length)tr.addClass("sel")});var ids=$('[name="id-copie"]').val();$("#u"+ids.replace(/,/g,",#u")).prop("checked",true).change();ids=$('[name="id-bcc"]').val();$("#u"+ids.replace(/,/g,",#u")).parent().next().children().prop("checked",true).change();$(".categorie a",f).on("click keyup",function(){var classe=this.className.split(" ")[1];var etat=this.className.split(" ")[0]=="icon-cocher";var titre=this.title;$(this).parent().parent().nextUntil(".categorie").find("."+classe+":not(:disabled)").prop("checked",etat).change();this.className=(etat?"icon-decocher ":"icon-cocher ")+classe;this.title=this.title.replace(etat?"Cocher":"Décocher",etat?"Décocher":"Cocher");var classe2=classe=="dest"?"bcc":"dest";$(this).parent().parent().find(".icon-decocher."+classe2).each(function(){this.className="icon-cocher "+classe2;this.title="C"+this.title.substr(3)})});$(".gr input",f).on("click",function(){var ids=this.value;if(this.className=="dest")$("#u"+ids.replace(/,/g,",#u")).prop("checked",this.checked).change();else $("#u"+ids.replace(/,/g,",#u")).parent().next().children().prop("checked",this.checked).change()});$(".icon-ok",f).on("click",function(){$('[name="id-copie"]').val($("tr:not(.gr) .dest:checked",f).map(function(){return this.value}).get().join(","));$('[name="id-bcc"]').val($("tr:not(.gr) .bcc:checked",f).map(function(){return this.value}).get().join(","));$("#maildest").text($("tr:not(.gr) .dest:checked",f).parent().prev().map(function(){return this.textContent}).get().concat($("tr:not(.gr) .bcc:checked",f).parent().prev().prev().map(function(){return this.textContent+" (CC)"}).get()).join(", ")||"[Personne]");$("#fenetre, #fenetre_fond").remove()})}function envoimail(){if($(".maildest").children("span").text()=="[Personne]")affiche("Il faut au moins un destinataire pour envoyer le courriel.","nok");else if(!$('[name="sujet"]').val().length)affiche("Il faut un sujet non vide pour envoyer le courriel.","nok");else $.ajax({url:"ajax.php",method:"post",data:$("#mail").serialize(),dataType:"json",el:"",fonction:function(el){location.reload(true)}})}function relevenotes(){confirmation("<p>Vous allez réaliser une relève des notes de colles. Cela consiste à marquer comme relevées toutes les heures déclarées jusqu'à maintenant et non encore relevées. Vous pourrez alors télécharger le nouveau relevé au sein du tableau en bas de page.</p><p>Cette opération n'est pas annulable.</p><p>Une fois que vous aurez réalisé ce relevé, les professeurs et colleurs ne pourront pas modifier le nombre d'élèves et la durée correspondant aux colles relevées.</p>",this,function(el){$.ajax({url:"ajax.php",method:"post",data:"action=releve-notes",dataType:"json",el:"",fonction:function(el){location.reload(true)}})})}$(document).ajaxSend(function(ev,xhr,settings){$("#load").show(200);if(settings.data.append)settings.data.append("csrf-token",$("body").attr("data-csrf-token"));else settings.data="csrf-token="+$("body").attr("data-csrf-token")+"&"+settings.data}).ajaxStop(function(){$("#load").hide(200)}).ajaxSuccess(function(ev,xhr,settings){var data=xhr.responseJSON;switch(data["etat"]){case"ok":affiche(data["message"],"ok");settings.fonction(settings.el);break;case"nok":affiche(data["message"],"nok");break;case"login":case"mdp":reconnect(settings,data["etat"]=="mdp");break;case"recupok":settings.afficheform(data)}});$(function(){$("a.formulaire, .modifevnmt").on("click",formulaire);$("a.icon-aide").on("click",function(){popup($("#aide-"+($(this).parent().data("id")||"page").split("|")[0]).html(),false)});$("a.icon-ok").on("click",valide);$("a.icon-cache,a.icon-montre,a.icon-monte,a.icon-descend,a.icon-supprime,a.icon-lock,a.icon-ajoutecolle").on("click",function(){window[this.className.substring(5)]($(this))});$("#log").hide().on("click",function(){$(this).hide(300)});$(".editable").editinplace();$("a.icon-deconnexion").on("click",function(e){$.ajax({url:"ajax.php",method:"post",data:{action:"deconnexion"},dataType:"json",el:"",fonction:function(el){location.reload(true)}})});$(".titrecdt").editinplacecdt();$(".cdt-raccourcis").init_cdt_raccourcis();$(".icon-mailenvoi").on("click",envoimail);$("#maildest, #maildest + .icon-edite").on("click",destinatairesmail);$(".categorie th:first-child").prepend($('<span class="icon-deplie" title="Déplier/Replier cette catégorie"></span>').on("click",plie));$("article select[multiple]").each(selmult);$(".supprmultiple").on("click",suppressionmultiple);$("#utilisateurs").each(init_utilisateurs);$("#utilisateurs-matieres").each(init_utilisateurs_matieres);$(".usergrp").first().each(init_utilisateurs_groupes);$("#planning select").change(function(){$(this).parent().prev().children("input").prop("checked",this.value==0)});$("#planning input").change(function(){$(this).parent().next().children("select").val(0)});$("#relevenotes").on("click",relevenotes);$(".icon-menu").on("click",function(){$("#colonne,nav").toggleClass("visible")})});
\ No newline at end of file
diff -urN cahier-de-prepa8.0.2/js/fonctions.min18.js cahier-de-prepa8.1.0/js/fonctions.min18.js
--- cahier-de-prepa8.0.2/js/fonctions.min18.js	2018-10-16 10:57:56.471232706 +0200
+++ cahier-de-prepa8.1.0/js/fonctions.min18.js	1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-function affiche(message,etat){$("#log").removeClass().addClass(etat).html(message).append('<span class="icon-ferme"></span>').fadeIn().off("click").on("click",function(){window.clearTimeout(extinction);$(this).fadeOut(800)});extinction=window.setTimeout(function(){$("#log").fadeOut(800)},6e3)}$(document).ajaxSend(function(ev,xhr,settings){$("#load").show(200);if(settings.data.append)settings.data.append("csrf-token",$("body").attr("data-csrf-token"));else settings.data="csrf-token="+$("body").attr("data-csrf-token")+"&"+settings.data}).ajaxStop(function(){$("#load").hide(200)}).ajaxSuccess(function(ev,xhr,settings){var data=xhr.responseJSON;switch(data["etat"]){case"ok":affiche(data["message"],"ok");settings.fonction(settings.el);break;case"nok":affiche(data["message"],"nok");break}});$(function(){$("a.icon-connexion").on("click",function(e){if(!$("#log").length)$('<div id="log"></div>').appendTo("body").hide().on("click",function(){$(this).hide()});$("#colonne,nav").removeClass("visible");var el=$('<div id="fenetre"></div>').appendTo("body").html('<a class="icon-ferme" title="Fermer"></a><a class="icon-ok" title="Valider"></a><h3>Connexion</h3><form>  <p>Veuillez entrer votre identifiant et votre mot de passe&nbsp;:</p>  <input class="ligne" type="text" name="login" placeholder="Identifiant">  <input class="ligne" type="password" name="motdepasse" placeholder="Mot de passe">  <p class="oubli"><label for="permconn">Se souvenir de moi</label><input type="checkbox" name="permconn" id="permconn" value="1">  <p class="oubli"><a href="gestioncompte?oublimdp">Identifiant ou mot de passe oublié&nbsp;?</a></p>  <p class="oubli"><a href="gestioncompte?creation">Créer un compte</a></p></form>');$('<div id="fenetre_fond"></div>').appendTo("body").click(function(){$("#fenetre,#fenetre_fond").remove()});$("#fenetre a.icon-ferme").on("click",function(){$("#fenetre,#fenetre_fond").remove()});$("#fenetre a.icon-ok").on("click",function(){$.ajax({url:"ajax.php",method:"post",data:$("#fenetre form").serialize()+"&connexion=1",dataType:"json",el:"",beforeSend:function(){$("#load").show(200)},complete:function(){$("#load").hide(200)},fonction:function(el){location.reload(true)}}).done(function(data){if(data["etat"]=="nok")$("#fenetre form p:first").html(data["message"]).addClass("warning")})});$("#fenetre input").on("keypress",function(e){if(e.which==13){$("#fenetre a.icon-ok").click();return false}});$("#fenetre form input:first").focus()});$("a.icon-deconnexion").on("click",function(e){$.ajax({url:"ajax.php",method:"post",data:{action:"deconnexion"},dataType:"json",el:"",fonction:function(el){location.reload(true)}})});$(".icon-menu").on("click",function(){$("nav").toggleClass("visible");$("#recent").removeClass();$("#colonne").toggleClass("visible",$("nav").hasClass("visible"))});$(".icon-recent").on("click",function(){$("#recent").toggleClass("visible");$("nav").removeClass();$("#colonne").toggleClass("visible",$("#recent").hasClass("visible"))});$(".evnmt").on("click",function(){var donnees=evenements[this.id.substr(1)];var el=$('<div id="fenetre"></div>').appendTo("body").html("<h3>"+donnees.titrebis+'</h3>\n<h3 style="margin-bottom: 1em;">'+donnees.date+"</h3>\n<p>"+donnees.texte+"</p>").focus();$('<div id="fenetre_fond"></div>').appendTo("body").click(function(){$("#fenetre,#fenetre_fond").remove()});$('<a class="icon-ferme" title="Fermer"></a>').prependTo(el).on("click",function(){el.remove();$("#fenetre_fond").remove()})})});
diff -urN cahier-de-prepa8.0.2/js/fonctions.min.js cahier-de-prepa8.1.0/js/fonctions.min.js
--- cahier-de-prepa8.0.2/js/fonctions.min.js	1970-01-01 01:00:00.000000000 +0100
+++ cahier-de-prepa8.1.0/js/fonctions.min.js	2018-10-16 10:57:56.471232706 +0200
@@ -0,0 +1 @@
+function affiche(message,etat){$("#log").removeClass().addClass(etat).html(message).append('<span class="icon-ferme"></span>').fadeIn().off("click").on("click",function(){window.clearTimeout(extinction);$(this).fadeOut(800)});extinction=window.setTimeout(function(){$("#log").fadeOut(800)},6e3)}$(document).ajaxSend(function(ev,xhr,settings){$("#load").show(200);if(settings.data.append)settings.data.append("csrf-token",$("body").attr("data-csrf-token"));else settings.data="csrf-token="+$("body").attr("data-csrf-token")+"&"+settings.data}).ajaxStop(function(){$("#load").hide(200)}).ajaxSuccess(function(ev,xhr,settings){var data=xhr.responseJSON;switch(data["etat"]){case"ok":affiche(data["message"],"ok");settings.fonction(settings.el);break;case"nok":affiche(data["message"],"nok");break}});$(function(){$("a.icon-connexion").on("click",function(e){if(!$("#log").length)$('<div id="log"></div>').appendTo("body").hide().on("click",function(){$(this).hide()});$("#colonne,nav").removeClass("visible");var el=$('<div id="fenetre"></div>').appendTo("body").html('<a class="icon-ferme" title="Fermer"></a><a class="icon-ok" title="Valider"></a><h3>Connexion</h3><form>  <p>Veuillez entrer votre identifiant et votre mot de passe&nbsp;:</p>  <input class="ligne" type="text" name="login" placeholder="Identifiant">  <input class="ligne" type="password" name="motdepasse" placeholder="Mot de passe">  <p class="oubli"><label for="permconn">Se souvenir de moi</label><input type="checkbox" name="permconn" id="permconn" value="1">  <p class="oubli"><a href="gestioncompte?oublimdp">Identifiant ou mot de passe oublié&nbsp;?</a></p>  <p class="oubli"><a href="gestioncompte?creation">Créer un compte</a></p></form>');$('<div id="fenetre_fond"></div>').appendTo("body").click(function(){$("#fenetre,#fenetre_fond").remove()});$("#fenetre a.icon-ferme").on("click",function(){$("#fenetre,#fenetre_fond").remove()});$("#fenetre a.icon-ok").on("click",function(){$.ajax({url:"ajax.php",method:"post",data:$("#fenetre form").serialize()+"&connexion=1",dataType:"json",el:"",beforeSend:function(){$("#load").show(200)},complete:function(){$("#load").hide(200)},fonction:function(el){location.reload(true)}}).done(function(data){if(data["etat"]=="nok")$("#fenetre form p:first").html(data["message"]).addClass("warning")})});$("#fenetre input").on("keypress",function(e){if(e.which==13){$("#fenetre a.icon-ok").click();return false}});$("#fenetre form input:first").focus()});$("a.icon-deconnexion").on("click",function(e){$.ajax({url:"ajax.php",method:"post",data:{action:"deconnexion"},dataType:"json",el:"",fonction:function(el){location.reload(true)}})});$(".icon-menu").on("click",function(){$("nav").toggleClass("visible");$("#recent").removeClass();$("#colonne").toggleClass("visible",$("nav").hasClass("visible"))});$(".icon-recent").on("click",function(){$("#recent").toggleClass("visible");$("nav").removeClass();$("#colonne").toggleClass("visible",$("#recent").hasClass("visible"))});$(".evnmt").on("click",function(){var donnees=evenements[this.id.substr(1)];var el=$('<div id="fenetre"></div>').appendTo("body").html("<h3>"+donnees.titrebis+'</h3>\n<h3 style="margin-bottom: 1em;">'+donnees.date+"</h3>\n<p>"+donnees.texte+"</p>").focus();$('<div id="fenetre_fond"></div>').appendTo("body").click(function(){$("#fenetre,#fenetre_fond").remove()});$('<a class="icon-ferme" title="Fermer"></a>').prependTo(el).on("click",function(){el.remove();$("#fenetre_fond").remove()})})});
diff -urN cahier-de-prepa8.0.2/MAJSQL.sql cahier-de-prepa8.1.0/MAJSQL.sql
--- cahier-de-prepa8.0.2/MAJSQL.sql	2018-10-19 00:45:32.623040227 +0200
+++ cahier-de-prepa8.1.0/MAJSQL.sql	2018-10-27 23:58:40.422670805 +0200
@@ -418,7 +418,7 @@
 
 --
 -- Voilà les modifications à effectuer sur chaque base pour passer de Cahier de
--- Prépa 6.2.0 à Cahier de Prépa 8.0.0
+-- Prépa 6.2.0 à Cahier de Prépa 8.0.1
 --
 -- Nouvelles colonnes et tables
 ALTER TABLE groupes
@@ -490,3 +490,9 @@
 UPDATE utilisateurs SET mailenvoi = 1 WHERE autorisation > 2 AND mail > '';
 UPDATE utilisateurs SET mailliste = 1 WHERE autorisation > 1 AND mail > '';
 
+--
+-- Voilà les modifications à effectuer sur chaque base pour passer de Cahier de
+-- Prépa 8.0.2 à Cahier de Prépa 8.1.0
+--
+ALTER TABLE heurescolles 
+  ADD description VARCHAR(200) NOT NULL AFTER duree;
diff -urN cahier-de-prepa8.0.2/notes.php cahier-de-prepa8.1.0/notes.php
--- cahier-de-prepa8.0.2/notes.php	2018-10-17 01:11:56.925053433 +0200
+++ cahier-de-prepa8.1.0/notes.php	2018-10-30 05:17:45.144160493 +0100
@@ -40,7 +40,7 @@
 // Si $_REQUEST['cle'] existe, on la cherche dans les matières disponibles.
 // notes=0 : pas de note saisie
 // notes=1 : déjà des notes saisies
-// notes = 2 : fonction désactivée, pas d'affichage
+// notes=2 : fonction désactivée, pas d'affichage
 $resultat = $mysqli->query("SELECT id, cle, nom, dureecolle FROM matieres WHERE FIND_IN_SET(id,'${_SESSION['matieres']}') AND notes < 2");
 if ( $resultat->num_rows )  {
   if ( !empty($_REQUEST) )  {
@@ -154,23 +154,11 @@
     return ($duree%60).'m';
   }
 
-  // Pour les professeurs : affichage d'un récapitulatif pour tous les colleurs
-  // de la matière et possibilité d'affichage d'un tableau de notes global
+  // Pour les professeurs : affichage d'un tableau de notes global ou
+  // d'un récapitulatif pour tous les colleurs de la matière
   if ( $autorisation == 5 )  {
-    // Icônes d'actions générales
-    echo <<<FIN
-  
-  <div id="icones">
-    <a class="icon-ajoute formulaire" title="Ajouter des notes de colles"></a>
-    <a class="icon-prefs formulaire" title="Modifier les réglages des notes de colles"></a>
-    <a class="icon-voirtout" href="?${matiere['cle']}&amp;tableau" title="Voir le tableau de notes"></a>
-    <a class="icon-download" href="?${matiere['cle']}&amp;xls" title="Télécharger le tableau de notes en xls"></a>
-    <a class="icon-aide" title="Aide pour les modifications des notes de colles"></a>
-  </div>
-
-FIN;
 
-    // Tableau récapitulatif
+    // Affichage unique du tableau récapitulatif
     if ( isset($_REQUEST['tableau']) )  {
       // Récupération des colleurs
       $resultat = $mysqli->query("SELECT id, IF(LENGTH(nom),CONCAT(prenom,' ',nom),login) AS nom
@@ -179,14 +167,18 @@
       while ( $r = $resultat->fetch_assoc() )
         $select_colleurs .= "\n      <option value=\"${r['id']}\">${r['nom']}</option>";
       $resultat->free();
-      // Barre de sélection
+      // Icônes d'action générales et barre de sélection
       echo <<<FIN
 
+  <div id="icones">
+    <a class="icon-download" href="?${matiere['cle']}&amp;xls" title="Télécharger le tableau de notes en xls"></a>
+    <a class="icon-retour" href="?${matiere['cle']}" title="Revenir à l'affichage normal"></a>
+  </div>
+
   <p id="recherchenote" class="topbarre">
     Voir les notes de <select id="colleurs" onchange="if (this.value>0) { $('[data-colleur]').attr('class','collnosel'); $('[data-colleur=&quot;'+this.value+'&quot;]').attr('class','collsel'); } else $('[data-colleur]').removeClass();">
       <option value="0">tous les colleurs</option>$select_colleurs
     </select>
-    <a class="icon-ferme" title="Fermer le tableau" href="?${matiere['cle']}"></a>
   </p>
 
 FIN;
@@ -211,20 +203,34 @@
           else
             echo "      <tr>${r['nom']}<td class=\"pasnote\" colspan=\"$nb+1\">Pas encore de note pour cet élève</td></tr>\n";
         $resultat->free();
-        echo "    </tbody>\n  </table>\n";
+        echo "    </tbody>\n  </table>\n\n";
       }
       else
-        echo "\n  <article>\n    <h2>Il n'y a encore aucune note de colle en ${matiere['nom']} cette année.</h2>\n  </article>\n";
+        echo "\n  <article>\n    <h2>Il n'y a encore aucune note de colle en ${matiere['nom']} cette année.</h2>\n  </article>\n\n";
+      echo '  <p id="log"></p>';
+      fin(true);
     }
     
+    // Affichage "normal" : Récapitulatif de la matière
+    echo <<<FIN
+  
+  <div id="icones">
+    <a class="icon-ajoute formulaire" title="Ajouter des notes de colles"></a>
+    <a class="icon-prefs formulaire" title="Modifier les réglages des notes de colles"></a>
+    <a class="icon-voirtout" href="?${matiere['cle']}&amp;tableau" title="Voir le tableau de notes"></a>
+    <a class="icon-download" href="?${matiere['cle']}&amp;xls" title="Télécharger le tableau de notes en xls"></a>
+    <a class="icon-aide" title="Aide pour les modifications des notes de colles"></a>
+  </div>
+
+FIN;
+
     // Récupération du décompte de la matière
     $resultat = $mysqli->query("SELECT COUNT(*) FROM notes WHERE matiere = $mid");
     $r = $resultat->fetch_row();
     $resultat->free();
-    //~ $resultat = $mysqli->query("SELECT IF(LENGTH(nom),CONCAT(LEFT(prenom,1),'. ',nom),login), SUM(nb), SUM(duree*(releve>0)), SUM(duree*(releve=0)) 
-                                //~ FROM heurescolles AS h LEFT JOIN (SELECT COUNT(*) AS nb, heure FROM notes GROUP BY heure) AS n ON h.id = n.heure LEFT JOIN utilisateurs AS u ON h.colleur=u.id
-                                //~ WHERE h.matiere = $mid GROUP BY h.colleur");
-    $resultat = $mysqli->query("SELECT colleur, IF(LENGTH(nom),CONCAT(LEFT(prenom,1),'. ',nom),login), SUM(duree*(releve>0)), SUM(duree*(releve=0)) 
+    $resultat = $mysqli->query("SELECT colleur AS cid, IF(LENGTH(nom),CONCAT(LEFT(prenom,1),'. ',nom),login) AS cnom,
+                                       SUM(duree*(releve>0)) AS total_rel, SUM(duree*(releve>0)*(description>'')) AS td_rel,
+                                       SUM(duree*(releve=0)) AS total_nrel, SUM(duree*(releve=0)*(description>'')) AS td_nrel
                                 FROM heurescolles AS h LEFT JOIN utilisateurs AS u ON h.colleur=u.id
                                 WHERE matiere = $mid GROUP BY colleur ORDER BY IF(LENGTH(nom),nom,login)");
     if ( $resultat->num_rows )  {
@@ -236,25 +242,32 @@
         <tr><th></th>
 
 FIN;
-      $ligne_eleves = $ligne_heures1 = $ligne_heures2 = $ligne_moyenne = '';
-      $total = array(0,0,0);
-      while ( $r = $resultat->fetch_row() )  {
-        $resultat2 = $mysqli->query("SELECT COUNT(*), LEFT(REPLACE(AVG(IF(note='abs' OR note='nn',NULL,REPLACE(note,',','.'))),'.',','),4) FROM notes WHERE colleur = ${r[0]} AND matiere = $mid");
-        $s = $resultat2->fetch_row();
+      $ligne_eleves = $ligne_heures_rel = $ligne_heures_nrel = $ligne_heures = $ligne_moyenne = '';
+      $total = array('nb'=>0,'total_rel'=>0,'td_rel'=>0,'total_nrel'=>0,'td_nrel'=>0);
+      while ( $r = $resultat->fetch_assoc() )  {
+        $resultat2 = $mysqli->query("SELECT COUNT(*) AS nb, LEFT(REPLACE(AVG(IF(note='abs' OR note='nn',NULL,REPLACE(note,',','.'))),'.',','),4) AS moy FROM notes WHERE colleur = ${r['cid']} AND matiere = $mid");
+        $s = $resultat2->fetch_assoc();
         $resultat2->free();
-        echo "          <th class=\"colleurs\"><span>${r[1]}</span></th>\n";
-        $ligne_eleves .= "<td>${s[0]}</td>";
-        $ligne_heures1 .= '<td>'.format_duree($r[2]).'</td>';
-        $ligne_heures2 .= '<td>'.format_duree($r[3]).'</td>';
-        $ligne_moyenne .= "<td>${s[1]}</td>";
-        $total[0] += $s[0];
-        $total[1] += $r[2];
-        $total[2] += $r[3];
+        echo "          <th class=\"colleurs\"><span>${r['cnom']}</span></th>\n";
+        $ligne_eleves .= "<td>${s['nb']}</td>";
+        $ligne_heures_rel .= '<td>'.format_duree($r['total_rel']).( $r['td_rel'] ? '&nbsp;('.format_duree($r['td_rel']).')' : '' ).'</td>';
+        $ligne_heures_nrel .= '<td>'.format_duree($r['total_nrel']).( $r['td_nrel'] ? '&nbsp;('.format_duree($r['td_nrel']).')' : '' ).'</td>';
+        $ligne_heures .= '<td>'.format_duree($r['total_rel']+$r['total_nrel']).( ($d=$r['td_rel']+$r['td_nrel']) ? '&nbsp;('.format_duree($d).')' : '' ).'</td>';
+        $ligne_moyenne .= "<td>${s['moy']}</td>";
+        $total['nb'] += $s['nb'];
+        $total['total_rel'] += $r['total_rel'];
+        $total['td_rel'] += $r['td_rel'];
+        $total['total_nrel'] += $r['total_nrel'];
+        $total['td_nrel'] += $r['td_nrel'];
       }
       $resultat->free();
       // Totaux d'heures
-      $total[1] = format_duree($total[1]);
-      $total[2] = format_duree($total[2]);
+      $ligne_heures_rel = ( $total['td_rel'] ? "<tr><th>Nombre d'heures relevées (dont séances sans note)</th>$ligne_heures_rel<td>".format_duree($total['total_rel']).'&nbsp;('.format_duree($total['td_rel']).')</td></tr>'
+                                             : "<tr><th>Nombre d'heures relevées</th>$ligne_heures_rel<td>".format_duree($total['total_rel']).'</td></tr>' );
+      $ligne_heures_nrel = ( $total['td_nrel'] ? "<tr><th>Nombre d'heures non relevées (dont séances sans note)</th>$ligne_heures_nrel<td>".format_duree($total['total_nrel']).'&nbsp;('.format_duree($total['td_nrel']).')</td></tr>'
+                                               : "<tr><th>Nombre d'heures non relevées</th>$ligne_heures_nrel<td>".format_duree($total['total_nrel']).'</td></tr>' );
+      $ligne_heures = ( ($d=$total['td_rel']+$total['td_nrel']) ? "<tr><th>Nombre d'heures total (dont séances sans note)</th>$ligne_heures<td>".format_duree($total['total_rel']+$total['total_nrel']).'&nbsp;('.format_duree($d).')</td></tr>'
+                                                                : "<tr><th>Nombre d'heures total</th>$ligne_heures<td>".format_duree($total['total_rel']).'</td></tr>' );
       // Moyenne globale
       $resultat = $mysqli->query("SELECT LEFT(REPLACE(AVG(IF(note='abs' OR note='nn',NULL,REPLACE(note,',','.'))),'.',','),4) FROM notes WHERE matiere = $mid");
       $r = $resultat->fetch_row();
@@ -262,9 +275,10 @@
       echo <<<FIN
           <th class="colleurs"><span>Total</span></th>
         </tr>
-        <tr><th>Nombre d'élèves interrogés</th>$ligne_eleves<td>${total[0]}</td></tr>
-        <tr><th>Nombre d'heures relevées</th>$ligne_heures1<td>${total[1]}</td></tr>
-        <tr><th>Nombre d'heures non relevées</th>$ligne_heures2<td>${total[2]}</td></tr>
+        <tr><th>Nombre d'élèves interrogés</th>$ligne_eleves<td>${total['nb']}</td></tr>
+        $ligne_heures
+        $ligne_heures_rel
+        $ligne_heures_nrel
         <tr><th>Moyenne</th>$ligne_moyenne<td>${r[0]}</td></tr>
       </tbody>
     </table>
@@ -273,7 +287,7 @@
 FIN;
     }
   }
-  // Pour les colleurs : affichage d'un récapitulatif personnel
+  // Pour les colleurs : récapitulatif personnel uniquement
   else  {
     echo <<<FIN
   
@@ -285,20 +299,27 @@
 FIN;
 
     // Récupération du décompte personnel
-    $resultat = $mysqli->query("SELECT COUNT(*), LEFT(REPLACE(AVG(IF(note='abs' OR note='nn',NULL,REPLACE(note,',','.'))),'.',','),4) FROM notes WHERE colleur = ${_SESSION['id']} AND matiere = $mid");
-    $r = $resultat->fetch_row();
+    $resultat = $mysqli->query("SELECT SUM(duree*(releve>0)) AS total_rel, SUM(duree*(releve>0)*(description>'')) AS td_rel,
+                                       SUM(duree*(releve=0)) AS total_nrel, SUM(duree*(releve=0)*(description>'')) AS td_nrel
+                                FROM heurescolles WHERE colleur = ${_SESSION['id']} AND matiere = $mid");
+    $r = $resultat->fetch_assoc();
     $resultat->free();
-    $resultat = $mysqli->query("SELECT SUM(duree*(releve>0)), SUM(duree*(releve=0)) FROM heurescolles WHERE colleur = ${_SESSION['id']} AND matiere = $mid");
-    $s = array_map('format_duree',$resultat->fetch_row());
+    $resultat = $mysqli->query("SELECT COUNT(*) AS nb, LEFT(REPLACE(AVG(IF(note='abs' OR note='nn',NULL,REPLACE(note,',','.'))),'.',','),4) AS moy FROM notes WHERE colleur = ${_SESSION['id']} AND matiere = $mid");
+    $s = $resultat->fetch_assoc();
     $resultat->free();
+    $moyenne = ( is_null($s['moy']) ? '-' : "${s['moy']}/20" );
+    $ligne_heures_rel = ( $r['td_rel'] ? '<p><strong>Nombre d\'heures relevées (dont séances sans note)</strong>&nbsp;:&nbsp;'.format_duree($r['total_rel']).'&nbsp;('.format_duree($r['td_rel']).')</p>'
+                                       : '<p><strong>Nombre d\'heures relevées</strong>&nbsp;:&nbsp;'.format_duree($r['total_rel']).'</p>' );
+    $ligne_heures_nrel = ( $r['td_nrel'] ? '<p><strong>Nombre d\'heures non relevées (dont séances sans note)</strong>&nbsp;:&nbsp;'.format_duree($r['total_nrel']).'&nbsp;('.format_duree($r['td_nrel']).')</p>'
+                                         : '<p><strong>Nombre d\'heures non relevées</strong>&nbsp;:&nbsp;'.format_duree($r['total_nrel']).'</p>' );
     echo <<<FIN
   
   <article>
     <h3>Récapitulatif personnel</h3>
-    <p><strong>Nombre d'élèves interrogés</strong>&nbsp;:&nbsp;${r[0]}</p>
-    <p><strong>Nombre d'heures relevées</strong>&nbsp;:&nbsp;${s[0]}</p>
-    <p><strong>Nombre d'heures non relevées</strong>&nbsp;:&nbsp;${s[1]}</p>
-    <p><strong>Moyenne</strong>&nbsp;:&nbsp;${r[1]}/20</p>
+    <p><strong>Nombre d'élèves interrogés</strong>&nbsp;:&nbsp;${s['nb']}</p>
+    $ligne_heures_rel
+    $ligne_heures_nrel
+    <p><strong>Moyenne</strong>&nbsp;:&nbsp;$moyenne</p>
   </article>
   
 FIN;
@@ -313,44 +334,66 @@
     $eleves[$r['id']] = $r;
   $resultat->free();
   
-  // Récupération de l'ensemble des notes mises, regroupées par heure
-  $resultat = $mysqli->query("SELECT h.id, n.semaine AS sid, DATE_FORMAT(jour,'%d/%m/%y') AS jour, TIME_FORMAT(h.heure,'%kh%i') AS heure, duree, DATE_FORMAT(releve,'%d/%m') AS releve,
-                              GROUP_CONCAT( eleve ORDER BY IF(LENGTH(nom),nom,login) SEPARATOR '|') AS eleves,
-                              GROUP_CONCAT( note  ORDER BY IF(LENGTH(nom),nom,login) SEPARATOR '|') AS notes
-                              FROM heurescolles AS h JOIN notes AS n ON n.heure = h.id JOIN utilisateurs AS e ON n.eleve = e.id
-                              WHERE h.colleur = ${_SESSION['id']} AND h.matiere = $mid
-                              GROUP BY h.id ORDER BY h.jour DESC, h.heure DESC");
-  // Affichage de l'ensemble des notes de l'année
-  if ( $resultat->num_rows )  {
+  // Détail personnel des colles déclarées : récupération de l'ensemble des
+  // notes mises, regroupées par heure - commun colleurs et professeurs
+  $limite = ( isset($_REQUEST['voirtout']) ? '' : 'LIMIT 10' );
+  $resultat = $mysqli->query("SELECT id, semaine AS sid,
+                              DATE_FORMAT(jour,'%d/%m/%y') AS jour, TIME_FORMAT(h.heure,'%kh%i') AS heure, duree,
+                              DATE_FORMAT(releve,'%d/%m') AS releve, description,
+                              GROUP_CONCAT( eleve ORDER BY nom SEPARATOR '|') AS eleves,
+                              GROUP_CONCAT( note  ORDER BY nom SEPARATOR '|') AS notes
+                              FROM heurescolles AS h 
+                              LEFT JOIN ( SELECT heure,semaine,note,eleve,IF(LENGTH(nom),nom,login) AS nom FROM notes JOIN utilisateurs AS e ON eleve = e.id ) AS n ON n.heure = id
+                              WHERE colleur = ${_SESSION['id']} AND matiere = $mid
+                              GROUP BY id ORDER BY h.jour DESC, h.heure DESC $limite");
+  // Affichage
+  if ( $n = $resultat->num_rows )  {
+    if ( isset($_REQUEST['voirtout']) || ( $n < 10 ) )  {
+      $titre = 'Liste de vos colles';
+      $icone = '';
+    }
+    else  {
+      $titre = 'Liste de vos dernières colles';
+      $icone = "<a class=\"icon-voirtout\" href=\"?${matiere['cle']}&amp;voirtout\"></a>\n    ";
+    }
     echo  <<<FIN
   <article>
-    <h3>Listes des colles réalisées</h3>
+    $icone<h3>$titre</h3>
     <table id="notes">
       <tbody>
-        <tr><th>Jour</th><th>Heure</th><th>Élèves (notes)</th><th>Durée</th><th>Relève</th><th></th></tr>
+        <tr><th>Jour</th><th>Heure</th><th>Élèves (notes) ou Description</th><th>Durée</th><th>Relève</th><th></th></tr>
 
 FIN;
+    // Affichage de chaque heure
     while ( $r = $resultat->fetch_assoc() )  {
       $heure = ( $r['heure'] == '0h00' ) ? '-' : $r['heure'];
       $duree = format_duree($r['duree']);
-      if ( substr($r['releve'],0,2) == '00' )  {
+      if ( $r['releve'] == '00/00' )  {
         $r['releve'] = '-';
         $supprime = "\n            <a class=\"icon-supprime\" title=\"Supprimer cette colle\"></a>";
       }
       else  {
         $supprime = '';
       }
-      $notes = array_combine(explode('|',$r['eleves']),explode('|',$r['notes']));
-      $texte = array();
-      foreach( $notes as $e => $n ) {
-        $texte[] = "{$eleves[$e]['initiale']} ($n)";
+      // Cas des séances de TD sans note
+      if ( is_null($r['sid']) )  {
+        $texte = $r['description'];
+        $data = '';
+      }
+      // Cas des colles classiques
+      else  {
+        $notes = array_combine(explode('|',$r['eleves']),explode('|',$r['notes']));
+        $texte = array();
+        foreach( $notes as $e => $n )
+          $texte[] = "{$eleves[$e]['initiale']} ($n)";
+        $texte = implode(', ',$texte);
+        $data = " data-eleves=\"${r['eleves']}\" data-notes=\"${r['notes']}\" data-sid=\"${r['sid']}\"";
       }
-      $texte = implode(', ',$texte);
       echo <<<FIN
         <tr>
           <td>${r['jour']}</td><td>$heure</td><td>$texte</td><td>$duree</td><td>${r['releve']}</td>
           <td class="icones" data-id="notes|${r['id']}">
-            <a class="icon-edite formulaire" data-eleves="${r['eleves']}" data-notes="${r['notes']}" data-sid="${r['sid']}" title="Éditer cette colle"></a>$supprime
+            <a class="icon-edite formulaire"$data title="Éditer cette colle"></a>$supprime
           </td>
         </tr>
 
@@ -367,6 +410,70 @@
   else
     echo "\n  <article>\n    <h2>Vous n'avez encore saisi aucune note en ${matiere['nom']} cette année.</h2>\n  </article>\n";
 
+  // Professeurs uniquement : détail des colles déclarées par tous les colleurs
+  if ( $autorisation == 5 )  {
+    $limite = ( isset($_REQUEST['voirtout']) ? '' : 'LIMIT 40' );
+    $resultat = $mysqli->query("SELECT IF(LENGTH(nom),CONCAT(LEFT(prenom,1),'. ',nom),login) AS colleur,
+                                DATE_FORMAT(jour,'%d/%m/%y') AS jour, TIME_FORMAT(h.heure,'%kh%i') AS heure, duree,
+                                DATE_FORMAT(releve,'%d/%m') AS releve, description,
+                                GROUP_CONCAT( eleve ORDER BY enom SEPARATOR '|') AS eleves,
+                                GROUP_CONCAT( note  ORDER BY enom SEPARATOR '|') AS notes
+                                FROM heurescolles AS h JOIN utilisateurs AS c ON colleur = c.id
+                                LEFT JOIN ( SELECT heure,note,eleve,IF(LENGTH(nom),nom,login) AS enom FROM notes JOIN utilisateurs AS e ON eleve = e.id ) AS n ON n.heure = h.id
+                                WHERE colleur != ${_SESSION['id']} AND matiere = $mid
+                                GROUP BY h.id ORDER BY h.jour DESC, h.heure DESC, nom $limite");
+    // Affichage
+    if ( $n = $resultat->num_rows )  {
+      if ( isset($_REQUEST['voirtout']) || ( $n < 40 ) )  {
+        $titre = 'Liste des colles de vos colleurs';
+        $icone = '';
+      }
+      else  {
+        $titre = 'Liste de des dernières colles de vos colleurs';
+        $icone = "<a class=\"icon-voirtout\" href=\"?${matiere['cle']}&amp;voirtout\"></a>\n    ";
+      }
+      echo  <<<FIN
+  <article>
+    $icone<h3>$titre</h3>
+    <table id="notes">
+      <tbody>
+        <tr><th>Colleur</th><th>Jour</th><th>Heure</th><th>Élèves (notes) ou Description</th><th>Durée</th><th>Relève</th></tr>
+
+FIN;
+      // Affichage de chaque heure
+      while ( $r = $resultat->fetch_assoc() )  {
+        $heure = ( $r['heure'] == '0h00' ) ? '-' : $r['heure'];
+        $duree = format_duree($r['duree']);
+        $releve = ( $r['releve'] == '00/00' ) ? '-' : $r['releve'];
+        // Cas des séances de TD sans note
+        if ( is_null($r['notes']) )
+          $texte = $r['description'];
+        // Cas des colles classiques
+        else  {
+          $notes = array_combine(explode('|',$r['eleves']),explode('|',$r['notes']));
+          $texte = array();
+          foreach( $notes as $e => $n ) {
+            $texte[] = "{$eleves[$e]['initiale']} ($n)";
+          }
+          $texte = implode(', ',$texte);
+        }
+        echo <<<FIN
+        <tr>
+          <td>${r['colleur']}</td><td>${r['jour']}</td><td>$heure</td><td>$texte</td><td>$duree</td><td>$releve</td>
+        </tr>
+
+FIN;
+      }
+      $resultat->free();
+      echo <<<FIN
+      </tbody>
+    </table>
+  </article>
+
+FIN;
+    }
+  }
+
   // Table contenant les élèves et les groupes
   $table = '';
   foreach ( $eleves as $id => $eleve )
@@ -457,13 +564,15 @@
   
   <form id="form-notes">
     <p class="ligne"><label for="jour">Jour&nbsp;: </label><input type="text" name="jour" value="<?php echo $r[1]; ?>" size="8"></p>
-    <p class="ligne"><label for="heure">Heure&nbsp;: </label><input type="text" name="heure" value="" size="8" placeholder="Heure de la colle (facultatif)"></p>
-    <p class="ligne"><label for="duree">Durée&nbsp;: </label><input type="text" name="duree" value="0h" size="8" placeholder="Durée de la colle (obligatoire)"></p>
+    <p class="ligne"><label for="heure">Heure&nbsp;: </label><input type="text" name="heure" value="" size="5" placeholder="Heure de la colle (facultatif)"></p>
+    <p class="ligne"><label for="duree">Durée&nbsp;: </label><input type="text" name="duree" value="0h" size="4" placeholder="Durée de la colle (obligatoire)"></p>
     <table class="notes">
       <tbody>
 <?php echo $table; ?>
       </tbody>
     </table>
+    <p class="ligne"><label for="description">Description&nbsp;: </label><input type="text" name="description" value="" size="100" placeholder="Description de la séance (obligatoire)"></p>
+    <p class="ligne"><label for="td">Séance de TD sans note&nbsp;: </label><input type="checkbox" name="td"></p>
     <div><select><option value="x"></option><option value="10">10</option><option value="11">11</option><option value="12">12</option><option value="13">13</option><option value="14">14</option><option value="15">15</option><option value="9">9</option><option value="8">8</option><option value="7">7</option><option value="6">6</option><option value="abs">Absent</option><option value="nn">Non noté</option><option value="16">16</option><option value="17">17</option><option value="18">18</option><option value="19">19</option><option value="20">20</option><option value="5">5</option><option value="4">4</option><option value="3">3</option><option value="2">2</option><option value="1">1</option><option value="0">0</option><option value="0,5">0,5</option><option value="1,5">1,5</option><option value="2,5">2,5</option><option value="3,5">3,5</option><option value="4,5">4,5</option><option value="5,5">5,5</option><option value="6,5">6,5</option><option value="7,5">7,5</option><option value="8,5">8,5</option><option value="9,5">9,5</option><option value="10,5">10,5</option><option value="11,5">11,5</option><option value="12,5">12,5</option><option value="13,5">13,5</option><option value="14,5">14,5</option><option value="15,5">15,5</option><option value="16,5">16,5</option><option value="17,5">17,5</option><option value="18,5">18,5</option><option value="19,5">19,5</option></select></div>
   </form>
   
@@ -480,14 +589,20 @@
 
   <div id="aide-page">
     <h3>Aide et explications</h3>
-    <p>Il est possible ici consulter les notes que vous avez mises, de les modifier en cliquant sur le bouton <span class="icon-edite"></span>, de les supprimer en cliquant sur le bouton <span class="icon-supprime"></span> (une confirmation sera demandée) et d'en ajouter en cliquant sur le bouton <span class="icon-ajoute"></span>.</p>
+    <p>Il est possible ici consulter les notes et heures de colles que vous avez déclarées, de les modifier en cliquant sur le bouton <span class="icon-edite"></span>, de les supprimer en cliquant sur le bouton <span class="icon-supprime"></span> (une confirmation sera demandée) et d'en ajouter en cliquant sur le bouton <span class="icon-ajoute"></span>.</p>
     <h4>Saisie des notes</h4>
     <p>Vous pouvez saisir les notes par heure de colle ou par jour. La durée est précalculée automatiquement, mais vous pouvez modifier la valeur calculée avant de valider votre saisie.</p>
     <p>Vous ne pouvez mettre des notes de colles que dans certaines matières. Les professeurs de la classe ont la possibilité de modifier les matières qui vous sont associées.</p>
     <p>Un élève ne peut avoir qu'une seule note par matière et par semaine. Dans les formulaires d'ajout ou de modification des notes, les élèves ayant déjà eu une note par un autre colleur lors de la semaine concernée sont indiqués et non notables.</p> 
+    <p>Une fois saisie, une colle peut être modifiée mais doit rester sur la même semaine, pour éviter les conflits de note.</p>
+    <h4>Saisie des séances sans note</h4>
+    <p>Vous pouvez également déclarer et modifier des séances de cours ou de travaux dirigés sans note, qui seront alors payés comme des colles si le lycée utilise ces saisies pour mettre au paiement vos heures. Les séances sans notes ne sont pas soumises aux mêmes restrictions de semaines que les colles.</p>
+    <h4>Vérification des professeurs</h4>
+    <p>Les professeurs de la classe peuvent voir et télécharger le détail des notes que vous avez mises. Ils ont aussi accès dans un tableau synthétique à l'ensemble des durées que vous avez déclarées, pour vos colles comme pour vos séances sans note.</p>
     <h4>Déclaration administrative</h4>   
-    <p>Si le lycée utilise ces saisies pour mettre au paiement vos heures, ce sont normalement les durées déclarées qui comptent. Il est ainsi possible de déclarer une heure pour un binôme. Attention, les textes officiels précisent que chaque heure de colle est indivisible, mais la question du budget global peut modifier cela. Il est nécessaire que l'ensemble des colleurs se comportent de façon identique à ce niveau&nbsp;: parlez-en au professeur référent.</p>
+    <p>Si le lycée utilise ces saisies pour mettre au paiement vos heures, ce sont normalement les durées déclarées qui comptent. Il est ainsi possible de déclarer une heure pour un binôme. Attention, les textes officiels précisent que chaque heure de colle est indivisible, mais la question du budget global peut modifier cela. Il est nécessaire que l'ensemble des colleurs se comportent de façon identique à ce niveau&nbsp;: parlez-en au professeur référent. L'administration a accès au détail des notes.</p>
     <p>Pour les colles relevées par l'administration, la date de la relève est inscrite dans le tableau et la colle n'est plus modifiable sur sa durée ni supprimable. Il est par contre toujours possible de modifier les notes saisies.</p>
+    <p>Pour les séances sans note relevées par l'administration, la date de la relève est inscrite dans le tableau et la séance n'est plus modifiable sur sa durée ni supprimable. Il est par contre toujours possible de modifier le jour de la séance ou sa description.</p>
     <h4>Absences et retards</h4>
     <p>Lorsqu'un élève est absent, il vaut mieux le noter dans la colle et le marquer absent. Il sera toujours possible de le noter plus tard. Si la colle est relevée par l'administration entre son absence et son rattrapage, la note reste modifiable.</p>
     <p>Les élèves ne peuvent pas avoir deux notes par semaine dans la même matière&nbsp;: il est toujours préférable de noter le jour initialement prévu dans le colloscope plutôt que le jour de rattrapage le cas échéant.</p>
@@ -497,16 +612,17 @@
 
   <div id="aide-edite">
     <h3>Aide et explications</h3>
-    <p>Ce formulaire permet de modifier, supprimer ou ajouter des notes pendant la semaine choisie. Il sera validé par un clic sur <span class="icon-ok"></span>, et abandonné (donc supprimé) par un clic sur <span class="icon-ferme"></span>.</p>
-    <p>La semaine déjà saisie n'est pas modifiable. Le jour de la colle est contraint dans cette semaine. L'heure est modifiable. Sa saisie n'est pas obligatoire.</p>
-    <p>La saisie peut contenir autant d'élèves que vous le souhaitez, ou correspondre à une heure unique. La durée de la colle s'adapte automatiquement à la hausse. Elle reste modifiable à tout instant.</p>
+    <p>Ce formulaire permet de modifier, supprimer ou ajouter des notes (ou la description pour les séances sans note) de la colle sélectionnée. Il sera validé par un clic sur <span class="icon-ok"></span>, et abandonné (donc supprimé) par un clic sur <span class="icon-ferme"></span>.</p>
+    <p>La semaine déjà saisie n'est pas modifiable. Le jour de la colle est contraint dans cette semaine. L'heure est modifiable. Sa saisie n'est pas obligatoire. La restriction des semaines est supprimée pour les séances sans note.</p>
+    <p>La saisie peut contenir autant d'élèves que vous le souhaitez, ou correspondre à une heure unique. La durée de la colle s'adapte automatiquement à la hausse. Elle reste modifiable aant validation.</p>
     <p>Si des groupes de colles ont été définis par les professeurs, vous pouvez cocher les cases correspondantes pour n'afficher que les notes déjà saisies et ces groupes-là. Les notes déjà saisies restent affichées lors du cochage/décochage des groupes, sauf lorsque vous venez de les modifier.</p>
     <p>Un élève ne peut avoir qu'une seule note par matière et par semaine. Les élèves ayant déjà eu une note par un autre colleur lors de la semaine concernée sont indiqués et non notables.</p>
     <p>Seules les notes non vides et visibles au moment où vous cliquez sur le bouton <span class="icon-ok"></span> sont effectivement envoyées pour l'enregistrement. Les notes que vous avez saisies mais qui ne sont pas affichées parce que vous avez décoché le groupe de colles correspondant ne sont pas envoyées.</p>
     <p>Les notes laissées vides ne sont pas enregistrées. En dehors des notes numériques, les choix possibles sont <em>Absent</em> et <em>Non noté</em>.</p>
     <h4>Déclaration administrative</h4>   
-    <p>Si le lycée utilise ces saisies pour mettre au paiement vos heures, ce sont normalement les durées déclarées qui comptent. Il est ainsi possible de déclarer une heure pour un binôme. Attention, les textes officiels précisent que chaque heure de colle est indivisible, mais la question du budget global peut modifier cela. Il est nécessaire que l'ensemble des colleurs se comportent de façon identique à ce niveau&nbsp;: parlez-en au professeur référent.</p>
+    <p>Si le lycée utilise ces saisies pour mettre au paiement vos heures, ce sont normalement les durées déclarées qui comptent. Il est ainsi possible de déclarer une heure pour un binôme. Attention, les textes officiels précisent que chaque heure de colle est indivisible, mais la question du budget global peut modifier cela. Il est nécessaire que l'ensemble des colleurs se comportent de façon identique à ce niveau&nbsp;: parlez-en au professeur référent. L'administration a accès au détail des notes.</p>
     <p>Pour les colles relevées par l'administration, la date de la relève est inscrite dans le tableau et la colle n'est plus modifiable sur sa durée ni supprimable. Il est par contre toujours possible de modifier les notes saisies.</p>
+    <p>Pour les séances sans note relevées par l'administration, la date de la relève est inscrite dans le tableau et la séance n'est plus modifiable sur sa durée ni supprimable. Il est par contre toujours possible de modifier le jour de la séance ou sa description.</p>
     <h4>Absences et retards</h4>
     <p>Lorsqu'un élève est absent, il vaut mieux le noter dans la colle et le marquer absent. Il sera toujours possible de le noter plus tard. Si la colle est relevée par l'administration entre son absence et son rattrapage, la note reste modifiable.</p>
     <p>Les élèves ne peuvent pas avoir deux notes par semaine dans la même matière&nbsp;: il est toujours préférable de noter le jour initialement prévu dans le colloscope plutôt que le jour de rattrapage le cas échéant.</p>
@@ -514,15 +630,17 @@
 
   <div id="aide-ajoute">
     <h3>Aide et explications</h3>
-    <p>Ce formulaire permet d'ajouter des notes. Il sera validé par un clic sur <span class="icon-ok"></span>, et abandonné (donc supprimé) par un clic sur <span class="icon-ferme"></span>.</p>
-    <p>Vous devez commencer par choisir la semaine correspondant aux notes que vous allez saisir. Vous pouvez ensuite choisir le jour dans cette semaine. La saisie de l'heure n'est pas obligatoire.</p>
+    <p>Ce formulaire permet d'ajouter des notes de colles ou de déclarer une séance sans note. Il sera validé par un clic sur <span class="icon-ok"></span>, et abandonné (donc supprimé) par un clic sur <span class="icon-ferme"></span>.</p>
+    <p>Pour des notes de colles, vous devez commencer par choisir la semaine correspondant aux notes que vous allez saisir. Vous pouvez ensuite choisir le jour dans cette semaine. La saisie de l'heure n'est pas obligatoire.</p>
     <p>Si des groupes de colles ont été définis par les professeurs, vous pouvez cocher les cases correspondantes pour n'afficher que les élèves de ces groupes-là.</p>
-    <p>La saisie peut contenir autant d'élèves que vous le souhaitez, ou correspondre à une heure unique. La durée de la colle s'adapte automatiquement à la hausse à chaque nouvelle note saisie. Elle reste modifiable à tout instant.</p>
+    <p>La saisie peut contenir autant d'élèves que vous le souhaitez, ou correspondre à une heure unique. La durée de la colle s'adapte automatiquement à la hausse à chaque nouvelle note saisie. Elle reste modifiable avant validation.</p>
     <p>Un élève ne peut avoir qu'une seule note par matière et par semaine. Les élèves ayant déjà eu une note par un autre colleur lors de la semaine choisie sont indiqués et non notables.</p>
     <p>Seules les notes non vides et visibles au moment où vous cliquez sur le bouton <span class="icon-ok"></span> sont effectivement envoyées pour l'enregistrement. Les notes que vous avez saisies mais qui ne sont pas affichées parce que vous avez décoché le groupe de colles correspondant ne sont pas envoyées.</p>
     <p>Les notes laissées vides ne sont pas enregistrées. En dehors des notes numériques, les choix possibles sont <em>Absent</em> et <em>Non noté</em>.</p>
+    <h4>Saisie des séances sans note</h4>
+    <p>Vous pouvez également déclarer une séance de cours ou de travaux dirigés sans note, qui sera alors payée comme une colle si le lycée utilise ces saisies pour mettre au paiement vos heures. Les séances sans notes ne sont pas soumises aux mêmes restrictions de semaines que les colles.</p>
     <h4>Déclaration administrative</h4>   
-    <p>Si le lycée utilise ces saisies pour mettre au paiement vos heures, ce sont normalement les durées déclarées qui comptent. Il est ainsi possible de déclarer une heure pour un binôme. Attention, les textes officiels précisent que chaque heure de colle est indivisible, mais la question du budget global peut modifier cela. Il est nécessaire que l'ensemble des colleurs se comportent de façon identique à ce niveau&nbsp;: parlez-en au professeur référent.</p>
+    <p>Si le lycée utilise ces saisies pour mettre au paiement vos heures, ce sont normalement les durées déclarées qui comptent. Il est ainsi possible de déclarer une heure pour un binôme. Attention, les textes officiels précisent que chaque heure de colle est indivisible, mais la question du budget global peut modifier cela. Il est nécessaire que l'ensemble des colleurs se comportent de façon identique à ce niveau&nbsp;: parlez-en au professeur référent. L'administration a accès au détail des notes. Les professeurs associés à la matières ont accès au détail de vos heures déclarées.</p>
     <p>Pour les colles relevées par l'administration, la date de la relève est inscrite dans le tableau et la colle n'est plus modifiable sur sa durée ni supprimable. Il est par contre toujours possible de modifier les notes saisies.</p>
     <h4>Absences et retards</h4>
     <p>Lorsqu'un élève est absent, il vaut mieux le noter dans la colle et le marquer absent. Il sera toujours possible de le noter plus tard. Si la colle est relevée par l'administration entre son absence et son rattrapage, la note reste modifiable.</p>
@@ -533,12 +651,15 @@
 
   <div id="aide-page">
     <h3>Aide et explications</h3>
-    <p>Il est possible ici consulter les notes que vous avez mises, de les modifier en cliquant sur le bouton <span class="icon-edite"></span>, de les supprimer en cliquant sur le bouton <span class="icon-supprime"></span> (une confirmation sera demandée) et d'en ajouter en cliquant sur le bouton <span class="icon-ajoute"></span>.</p>
+    <p>Il est possible ici consulter les notes et heures de colles que vous et vos colleurs avez déclarées, de modifier les vôtres en cliquant sur le bouton <span class="icon-edite"></span>, de les supprimer en cliquant sur le bouton <span class="icon-supprime"></span> (une confirmation sera demandée) et d'en ajouter en cliquant sur le bouton <span class="icon-ajoute"></span>.</p>
     <h4>Saisie des notes</h4>
     <p>Vous pouvez saisir les notes par heure de colle ou par jour. La durée est précalculée automatiquement, mais vous pouvez modifier la valeur calculée avant de valider votre saisie. La durée de colle par élève, permettant le précalcul, est modifiable dans les préférences accessibles en cliquant sur le bouton <span class="icon-prefs"></span>.</p>
     <p>Vous ne pouvez mettre des notes de colles que dans les matières qui vous sont associées. Ces associations sont modifiables à la <a href="utilisateurs-matieres">gestion utilisateurs-matieres</a>.</p>
     <p>Un élève ne peut avoir qu'une seule note par matière et par semaine. Dans les formulaires d'ajout ou de modification des notes, les élèves ayant déjà eu une note par un autre colleur lors de la semaine concernée sont indiqués et non notables.</p> 
-    <h4>Consultation globale des notes</h4>
+    <p>Une fois saisie, une colle peut être modifiée mais doit rester sur la même semaine, pour éviter les conflits de note.</p>
+    <h4>Saisie des séances sans note</h4>
+    <p>Vous pouvez également déclarer et modifier des séances de cours ou de travaux dirigés sans note, qui seront alors payés comme des colles si le lycée utilise ces saisies pour mettre au paiement vos heures. Les séances sans notes ne sont pas soumises aux mêmes restrictions de semaines que les colles.</p>
+    <h4>Consultation globale des notes et déclarations</h4>
     <p>En tant que professeur associé à cette matière, vous avez la possibilité de consulter en ligne et en téléchargement l'ensemble des notes qui ont été saisies par vos colleurs. Les utilisateurs de type colleurs n'ont pas droit à cette fonctionnalité.</p>
     <p>En tant que professeur, vous avez aussi la possibilité de consulter l'ensemble des heures déclarées. Vous pouvez grâce à cela savoir si vos colleurs sont en retard sur leurs déclarations et suivre les relevés de l'administration pour chaque colleur le cas échéant. Vous pouvez aussi vérifier les totaux du nombre d'élèves notés et du nombre d'heures déclarées réalisées.</p>
     <p>Les boutons généraux permettent les actions suivantes&nbsp;:</p>
@@ -548,28 +669,30 @@
       <li>le bouton <span class="icon-voirtout"></span> permet de voir en ligne ce tableau récapitulatif. Il est alors possible de faire ressortir les notes de chaque colleur séparément à l'aide d'un menu déroulant. Cet affichage peut alors être supprimé par un clic sur le bouton <span class="icon-ferme"></span>.</li>
     </ul>
     <h4>Déclaration administrative</h4>
-    <p>Si le lycée utilise ces saisies pour mettre au paiement vos heures, ce sont normalement les durées déclarées qui comptent. Il est ainsi possible de déclarer une heure pour un binôme. Attention, les textes officiels précisent que chaque heure de colle est indivisible, mais la question du budget global peut modifier cela. Il est nécessaire que l'ensemble des colleurs se comportent de façon identique à ce niveau et que l'équipe pédagogique soit cohérente. Pensez à en parler avec vos collègues et votre administration.</p>
+    <p>Si le lycée utilise ces saisies pour mettre au paiement vos heures, ce sont normalement les durées déclarées qui comptent. Il est ainsi possible de déclarer une heure pour un binôme. Attention, les textes officiels précisent que chaque heure de colle est indivisible, mais la question du budget global peut modifier cela. Il est nécessaire que l'ensemble des colleurs se comporte de façon identique à ce niveau et que l'équipe pédagogique soit cohérente. Pensez à en parler avec vos collègues et votre administration. L'administration a accès au détail des notes.</p>
     <p>Pour les colles relevées par l'administration, la date de la relève est inscrite dans le tableau et la colle n'est plus modifiable sur sa durée ni supprimable. Il est par contre toujours possible de modifier les notes saisies.</p>
+    <p>Pour les séances sans note relevées par l'administration, la date de la relève est inscrite dans le tableau et la séance n'est plus modifiable sur sa durée ni supprimable. Il est par contre toujours possible de modifier le jour de la séance ou sa description.</p>
     <h4>Absences et retards</h4>
     <p>Lorsqu'un élève est absent, il vaut mieux le noter dans la colle et le marquer absent. Il sera toujours possible de le noter plus tard. Si la colle est relevée par l'administration entre son absence et son rattrapage, la note reste modifiable.</p>
     <p>Les élèves ne peuvent pas avoir deux notes par semaine dans la même matière&nbsp;: il est toujours préférable de noter le jour initialement prévu dans le colloscope plutôt que le jour de rattrapage le cas échéant.</p>
     <h4>Autres paramétrage</h4>
-    <p>Toutes les semaines ne sont pas des semaines de colles et vous pouvez modifier quelles semaines sont associées ou non à des colles à la <a href="planning">gestion du planning</a>. Ce réglage est valable pour toutes les matières et est aussi utilisé pour afficher les programmes de colles.</p>
-    <p>La durée de colle par élève, qui permet de précalcul immédiat de la durée des colles, est propre à chaque matière. Vous pouvez la modifier dans les préférences accessibles en cliquant sur le bouton <span class="icon-prefs"></span>.</p>
+    <p>Toutes les semaines ne sont pas des semaines de colles et vous pouvez modifier quelles semaines sont associées ou non à des colles à la <a href="planning">gestion du planning</a>. Ce réglage est valable pour toutes les matières et est aussi utilisé pour afficher les programmes de colles. Ce réglage n'est pas utilisé pour les séances sans note.</p>
+    <p>La durée de colle par élève, qui permet le précalcul immédiat de la durée des colles, est propre à chaque matière. Vous pouvez la modifier dans les préférences accessibles en cliquant sur le bouton <span class="icon-prefs"></span>.</p>
   </div>
 
   <div id="aide-edite">
     <h3>Aide et explications</h3>
-    <p>Ce formulaire permet de modifier, supprimer ou ajouter des notes pendant la semaine choisie. Il sera validé par un clic sur <span class="icon-ok"></span>, et abandonné (donc supprimé) par un clic sur <span class="icon-ferme"></span>.</p>
-    <p>La semaine déjà saisie n'est pas modifiable. Le jour de la colle est contraint dans cette semaine. L'heure est modifiable. Sa saisie n'est pas obligatoire.</p>
-    <p>La saisie peut contenir autant d'élèves que vous le souhaitez, ou correspondre à une heure unique. La durée de la colle s'adapte automatiquement à la hausse. Elle reste modifiable à tout instant.</p>
+    <p>Ce formulaire permet de modifier, supprimer ou ajouter des notes (ou la description pour les séances sans note) de la colle sélectionnée. Il sera validé par un clic sur <span class="icon-ok"></span>, et abandonné (donc supprimé) par un clic sur <span class="icon-ferme"></span>.</p>
+    <p>La semaine déjà saisie n'est pas modifiable. Le jour de la colle est contraint dans cette semaine. L'heure est modifiable. Sa saisie n'est pas obligatoire. La restriction des semaines est supprimée pour les séances sans note.</p>
+    <p>La saisie peut contenir autant d'élèves que vous le souhaitez, ou correspondre à une heure unique. La durée de la colle s'adapte automatiquement à la hausse. Elle reste modifiable aant validation.</p>
     <p>Si des groupes de colles ont été définis, vous pouvez cocher les cases correspondantes pour n'afficher que les notes déjà saisies et ces groupes-là. Les notes déjà saisies restent affichées lors du cochage/décochage des groupes, sauf lorsque vous venez de les modifier. Vous pouvez définir et modifier les groupes de colles à la <a href="groupes">gestion des groupes</a>. Ces modifications sont valables pour toutes les matières auxquelles sont associés les élèves. Créer des groupes n'est pas obligatoire pour pouvoir saisir des notes.</p>
     <p>Un élève ne peut avoir qu'une seule note par matière et par semaine. Les élèves ayant déjà eu une note par un autre colleur lors de la semaine concernée sont indiqués et non notables.</p>
     <p>Seules les notes non vides et visibles au moment où vous cliquez sur le bouton <span class="icon-ok"></span> sont effectivement envoyées pour l'enregistrement. Les notes que vous avez saisies mais qui ne sont pas affichées parce que vous avez décoché le groupe de colles correspondant ne sont pas envoyées.</p>
     <p>Les notes laissées vides ne sont pas enregistrées. En dehors des notes numériques, les choix possibles sont <em>Absent</em> et <em>Non noté</em>.</p>
     <h4>Déclaration administrative</h4>
-    <p>Si le lycée utilise ces saisies pour mettre au paiement vos heures, ce sont normalement les durées déclarées qui comptent. Il est ainsi possible de déclarer une heure pour un binôme. Attention, les textes officiels précisent que chaque heure de colle est indivisible, mais la question du budget global peut modifier cela. Il est nécessaire que l'ensemble des colleurs se comportent de façon identique à ce niveau et que l'équipe pédagogique soit cohérente. Pensez à en parler avec vos collègues et votre administration.</p>
+    <p>Si le lycée utilise ces saisies pour mettre au paiement vos heures, ce sont normalement les durées déclarées qui comptent. Il est ainsi possible de déclarer une heure pour un binôme. Attention, les textes officiels précisent que chaque heure de colle est indivisible, mais la question du budget global peut modifier cela. Il est nécessaire que l'ensemble des colleurs se comportent de façon identique à ce niveau et que l'équipe pédagogique soit cohérente. Pensez à en parler avec vos collègues et votre administration. L'administration a accès au détail des notes.</p>
     <p>Pour les colles relevées par l'administration, la date de la relève est inscrite dans le tableau et la colle n'est plus modifiable sur sa durée ni supprimable. Il est par contre toujours possible de modifier les notes saisies.</p>
+    <p>Pour les séances sans note relevées par l'administration, la date de la relève est inscrite dans le tableau et la séance n'est plus modifiable sur sa durée ni supprimable. Il est par contre toujours possible de modifier le jour de la séance ou sa description.</p>
     <h4>Absences et retards</h4>
     <p>Lorsqu'un élève est absent, il vaut mieux le noter dans la colle et le marquer absent. Il sera toujours possible de le noter plus tard. Si la colle est relevée par l'administration entre son absence et son rattrapage, la note reste modifiable.</p>
     <p>Les élèves ne peuvent pas avoir deux notes par semaine dans la même matière&nbsp;: il est toujours préférable de noter le jour initialement prévu dans le colloscope plutôt que le jour de rattrapage le cas échéant.</p>
@@ -577,15 +700,17 @@
 
   <div id="aide-ajoute">
     <h3>Aide et explications</h3>
-    <p>Ce formulaire permet d'ajouter des notes. Il sera validé par un clic sur <span class="icon-ok"></span>, et abandonné (donc supprimé) par un clic sur <span class="icon-ferme"></span>.</p>
-    <p>Vous devez commencer par choisir la semaine correspondant aux notes que vous allez saisir. Vous pouvez ensuite choisir le jour dans cette semaine. La saisie de l'heure n'est pas obligatoire.</p>
+    <p>Ce formulaire permet d'ajouter des notes de colles ou de déclarer une séance sans note. Il sera validé par un clic sur <span class="icon-ok"></span>, et abandonné (donc supprimé) par un clic sur <span class="icon-ferme"></span>.</p>
+    <p>Pour des notes de colles, vous devez commencer par choisir la semaine correspondant aux notes que vous allez saisir. Vous pouvez ensuite choisir le jour dans cette semaine. La saisie de l'heure n'est pas obligatoire.</p>
     <p>Si des groupes de colles ont été définis, vous pouvez cocher les cases correspondantes pour n'afficher que les notes déjà saisies et ces groupes-là. Les notes déjà saisies restent affichées lors du cochage/décochage des groupes, sauf lorsque vous venez de les modifier. Vous pouvez définir et modifier les groupes de colles à la <a href="groupes">gestion des groupes</a>. Ces modifications sont valables pour toutes les matières auxquelles sont associés les élèves. Créer des groupes n'est pas obligatoire pour pouvoir saisir des notes.</p>
-    <p>La saisie peut contenir autant d'élèves que vous le souhaitez, ou correspondre à une heure unique. La durée de la colle s'adapte automatiquement à la hausse à chaque nouvelle note saisie. Elle reste modifiable à tout instant.</p>
+    <p>La saisie peut contenir autant d'élèves que vous le souhaitez, ou correspondre à une heure unique. La durée de la colle s'adapte automatiquement à la hausse à chaque nouvelle note saisie. Elle reste modifiable avant validation.</p>
     <p>Un élève ne peut avoir qu'une seule note par matière et par semaine. Les élèves ayant déjà eu une note par un autre colleur lors de la semaine choisie sont indiqués et non notables.</p>
     <p>Seules les notes non vides et visibles au moment où vous cliquez sur le bouton <span class="icon-ok"></span> sont effectivement envoyées pour l'enregistrement. Les notes que vous avez saisies mais qui ne sont pas affichées parce que vous avez décoché le groupe de colles correspondant ne sont pas envoyées.</p>
     <p>Les notes laissées vides ne sont pas enregistrées. En dehors des notes numériques, les choix possibles sont <em>Absent</em> et <em>Non noté</em>.</p>
+    <h4>Saisie des séances sans note</h4>
+    <p>Vous pouvez également déclarer une séance de cours ou de travaux dirigés sans note, qui sera alors payée comme une colle si le lycée utilise ces saisies pour mettre au paiement vos heures. Les séances sans notes ne sont pas soumises aux mêmes restrictions de semaines que les colles.</p>
     <h4>Déclaration administrative</h4>   
-    <p>Si le lycée utilise ces saisies pour mettre au paiement vos heures, ce sont normalement les durées déclarées qui comptent. Il est ainsi possible de déclarer une heure pour un binôme. Attention, les textes officiels précisent que chaque heure de colle est indivisible, mais la question du budget global peut modifier cela. Il est nécessaire que l'ensemble des colleurs se comportent de façon identique à ce niveau et que l'équipe pédagogique soit cohérente. Pensez à en parler avec vos collègues et votre administration.</p>
+    <p>Si le lycée utilise ces saisies pour mettre au paiement vos heures, ce sont normalement les durées déclarées qui comptent. Il est ainsi possible de déclarer une heure pour un binôme. Attention, les textes officiels précisent que chaque heure de colle est indivisible, mais la question du budget global peut modifier cela. Il est nécessaire que l'ensemble des colleurs se comportent de façon identique à ce niveau et que l'équipe pédagogique soit cohérente. Pensez à en parler avec vos collègues et votre administration. L'administration a accès au détail des notes.</p>
     <p>Pour les colles relevées par l'administration, la date de la relève est inscrite dans le tableau et la colle n'est plus modifiable sur sa durée ni supprimable. Il est par contre toujours possible de modifier les notes saisies.</p>
     <h4>Absences et retards</h4>
     <p>Lorsqu'un élève est absent, il vaut mieux le noter dans la colle et le marquer absent. Il sera toujours possible de le noter plus tard. Si la colle est relevée par l'administration entre son absence et son rattrapage, la note reste modifiable.</p>
diff -urN cahier-de-prepa8.0.2/relevenotes.php cahier-de-prepa8.1.0/relevenotes.php
--- cahier-de-prepa8.0.2/relevenotes.php	2018-10-18 22:57:34.963455378 +0200
+++ cahier-de-prepa8.1.0/relevenotes.php	2018-10-30 04:42:59.700112066 +0100
@@ -33,134 +33,198 @@
   return ($duree%60).'m';
 }
 
-//////////////////////////////////////
-// Exportation des décomptes en xls //
-//////////////////////////////////////
+///////////////////////////////////////////
+// Exportation en xls ou pour impression //
+///////////////////////////////////////////
+// Trois types d'exportation possible :
+// * decompte -> liste des colleurs/heures déclarées, en xls
+// * notes -> liste des notes, en xls
+// * impression -> affichage des deux listes en html, pour l'impression
 // Exportation uniquement si aucun header déjà envoyé
-if ( isset($_REQUEST['decompte']) && ctype_digit($decompte = $_REQUEST['decompte']) && !headers_sent() )  {
-  // Récupération de la bonne date et vérification
-  $decompte = preg_replace('/(\d{2})(\d{2})(\d{2})/','20$1-$2-$3',$decompte);
-  $resultat = $mysqli->query("SELECT IF(LENGTH(c.nom),CONCAT(c.nom,' ',c.prenom),c.login) AS colleur, m.nom AS matiere, SUM(nb) AS nb, SUM(duree) AS duree
-                              FROM heurescolles AS h JOIN (SELECT COUNT(*) AS nb, heure FROM notes GROUP BY heure) AS n ON h.id = n.heure
-                              JOIN utilisateurs AS c ON h.colleur = c.id JOIN matieres AS m ON h.matiere = m.id
-                              WHERE h.releve = '$decompte' GROUP BY h.colleur ORDER BY c.nom, m.ordre");
-  $mysqli->close();
-  if ( $resultat->num_rows )  {
-    // Fonctions de saisie
-    function saisie_nombre($l, $c, $v)  {
-      echo pack("sssss", 0x203, 14, $l, $c, 0).pack("d", $v);
-      return;
-    }
-    function saisie_chaine($l, $c, $v)  {
-      echo pack("ssssss", 0x204, 8 + strlen($v), $l, $c, 0, strlen($v)).$v;
-      return;
-    }
-    // Envoi des headers
-    header("Content-Type: application/vnd.ms-excel");
-    header("Content-Disposition: attachment; filename=decompte-$decompte.xls");
-    header("Content-Transfer-Encoding: binary");
-    // Début du fichier xls
-    echo pack("sssss", 0x809, 6, 0, 0x10, 0);
-    // Remplissage
-    saisie_chaine(0, 0, utf8_decode('Relevé des heures de colles - '.preg_replace('/(\d{4})-(\d{2})-(\d{2})/','$3/$2/$1',$decompte)));
-    saisie_chaine(2, 0, 'Colleur');
-    saisie_chaine(2, 1, utf8_decode('Matière'));
-    saisie_chaine(2, 2, utf8_decode('Nombre d\'élèves'));
-    saisie_chaine(2, 3, utf8_decode('Durée déclarée'));
-    $i = 2;
-    $total_n = 0;
-    $total_duree = 0;
-    while ( $r = $resultat->fetch_assoc() )  {
-      saisie_chaine(++$i, 0, utf8_decode($r['colleur']));
-      saisie_chaine($i, 1, utf8_decode($r['matiere']));
-      saisie_nombre($i, 2, $r['nb']);
-      saisie_chaine($i, 3, format_duree($r['duree']));
-      $total_n += $r['nb'];
-      $total_duree += $r['duree'];
-    }
-    // Totaux
-    saisie_chaine($i = $i+2, 0, 'Total');
-    saisie_nombre($i, 2, $total_n);
-    saisie_chaine($i, 3, format_duree($total_duree));
-    // Fin du fichier xls
-    echo pack("ss", 0x0A, 0x00);
-    $resultat->free();
-    exit();
+if ( isset($_REQUEST['datereleve']) && ctype_digit($date = $_REQUEST['datereleve']) && !headers_sent() )  {
+  // Récupération du titre du Cahier
+  $resultat = $mysqli->query('SELECT titre FROM pages WHERE id = 1');
+  $r = $resultat->fetch_row();
+  $resultat->free();
+  $titre = $r[0];
+  // Récupération de la bonne date
+  $date = preg_replace('/(\d{2})(\d{2})(\d{2})/','20$1-$2-$3',$date);
+  // Requêtes possibles
+  $requete_decompte = "SELECT IF(LENGTH(c.nom),CONCAT(c.nom,' ',c.prenom),c.login) AS colleur, m.nom AS matiere,
+                              SUM(nb) AS nb, SUM(duree*(description>'')) AS duree_td, SUM(duree) AS duree
+                      FROM heurescolles AS h LEFT JOIN utilisateurs AS c ON colleur = c.id LEFT JOIN matieres AS m ON matiere = m.id
+                      LEFT JOIN (SELECT COUNT(*) AS nb, heure FROM notes GROUP BY heure) AS n ON h.id = n.heure
+                      WHERE h.releve = '$date' GROUP BY h.colleur ORDER BY c.nom, m.ordre";
+  $requete_notes =    "SELECT h.id, IF(LENGTH(c.nom),CONCAT(LEFT(prenom,1),'. ',c.nom),login) AS colleur, eleve,
+                              m.nom AS matiere, DATE_FORMAT(jour,'%d/%m/%y') AS jour, TIME_FORMAT(h.heure,'%kh%i') AS heure, duree,
+                              note, description, duree
+                      FROM heurescolles AS h JOIN utilisateurs AS c ON colleur = c.id JOIN matieres AS m ON matiere = m.id
+                      LEFT JOIN ( SELECT heure,note,IF(LENGTH(nom),CONCAT(nom,' ',prenom),login) AS eleve 
+                                  FROM notes JOIN utilisateurs AS e ON eleve = e.id ) AS n ON n.heure = h.id
+                      WHERE releve = '$date' ORDER BY c.nom, h.jour, h.heure, eleve";                      
+  // Fonctions de saisie xls
+  function saisie_nombre($l, $c, $v)  {
+    echo pack("sssss", 0x203, 14, $l, $c, 0).pack("d", $v);
   }
-}
-
-//////////////////////////////////
-// Exportation des notes en xls //
-//////////////////////////////////
-// Exportation uniquement si aucun header déjà envoyé
-if ( isset($_REQUEST['notes']) && ctype_digit($decompte = $_REQUEST['notes']) && !headers_sent() )  {
-  // Récupération de la bonne date et vérification
-  $decompte = preg_replace('/(\d{2})(\d{2})(\d{2})/','20$1-$2-$3',$decompte);
-  $resultat = $mysqli->query("SELECT h.id, IF(LENGTH(c.nom),CONCAT(c.nom,' ',c.prenom),c.login) AS colleur, IF(LENGTH(e.nom),CONCAT(e.nom,' ',e.prenom),e.login) AS eleve,
-                              m.nom AS matiere, DATE_FORMAT(jour,'%d/%m/%y') AS jour, TIME_FORMAT(h.heure,'%kh%i') AS heure, note, duree
-                              FROM notes AS n JOIN heurescolles AS h ON h.id = n.heure JOIN utilisateurs AS e ON n.eleve = e.id
-                              JOIN utilisateurs AS c ON n.colleur = c.id JOIN matieres AS m ON n.matiere = m.id
-                              WHERE h.releve = '$decompte' ORDER BY c.nom, h.jour, h.heure, e.nom");
-  $mysqli->close();
-  if ( $resultat->num_rows )  {
-    // Fonctions de saisie
-    function saisie_nombre($l, $c, $v)  {
-      echo pack("sssss", 0x203, 14, $l, $c, 0).pack("d", $v);
-      return;
+  function saisie_chaine($l, $c, $v)  {
+    echo pack("ssssss", 0x204, 8 + strlen($v), $l, $c, 0, strlen($v)).$v;
+  }
+  // Exportation
+  switch ( $_REQUEST['export'] )  {
+    case 'decompte':  {
+      $resultat = $mysqli->query($requete_decompte);
+      $mysqli->close();
+      if ( $resultat->num_rows )  {
+        // Envoi des headers
+        header("Content-Type: application/vnd.ms-excel");
+        header("Content-Disposition: attachment; filename=decompte-$date.xls");
+        header("Content-Transfer-Encoding: binary");
+        // Début du fichier xls
+        echo pack("sssss", 0x809, 6, 0, 0x10, 0);
+        // Remplissage
+        saisie_chaine(0, 0, utf8_decode('Relevé des heures de colles du '.preg_replace('/(\d{4})-(\d{2})-(\d{2})/','$3/$2/$1',$date).' - '.$titre));
+        saisie_chaine(2, 0, 'Colleur');
+        saisie_chaine(2, 1, utf8_decode('Matière'));
+        saisie_chaine(2, 2, utf8_decode('Nombre d\'élèves'));
+        saisie_chaine(2, 3, utf8_decode('Séances sans note'));
+        saisie_chaine(2, 4, utf8_decode('Durée totale déclarée'));
+        $i = 2;
+        $total_n = $total_duree = $total_duree_td = 0;
+        while ( $r = $resultat->fetch_assoc() )  {
+          saisie_chaine(++$i, 0, utf8_decode($r['colleur']));
+          saisie_chaine($i, 1, utf8_decode($r['matiere']));
+          saisie_nombre($i, 2, $r['nb']);
+          saisie_chaine($i, 3, format_duree($r['duree_td']));
+          saisie_chaine($i, 4, format_duree($r['duree']));
+          $total_n += $r['nb'];
+          $total_duree_td += $r['duree_td'];
+          $total_duree += $r['duree'];
+        }
+        // Totaux
+        saisie_chaine($i = $i+2, 0, 'Total');
+        saisie_nombre($i, 2, $total_n);
+        saisie_chaine($i, 3, format_duree($total_duree_td));
+        saisie_chaine($i, 4, format_duree($total_duree));
+        // Fin du fichier xls
+        echo pack("ss", 0x0A, 0x00);
+        $resultat->free();
+      }
+      exit();
     }
-    function saisie_chaine($l, $c, $v)  {
-      echo pack("ssssss", 0x204, 8 + strlen($v), $l, $c, 0, strlen($v)).$v;
-      return;
+    case 'notes':  {
+      $resultat = $mysqli->query($requete_notes);
+      $mysqli->close();
+      if ( $resultat->num_rows )  {
+        // Envoi des headers
+        header("Content-Type: application/vnd.ms-excel");
+        header("Content-Disposition: attachment; filename=decompte-$date.xls");
+        header("Content-Transfer-Encoding: binary");
+        // Début du fichier xls
+        echo pack("sssss", 0x809, 6, 0, 0x10, 0);
+        // Remplissage
+        saisie_chaine(0, 0, utf8_decode('Détail des notes de colles du '.preg_replace('/(\d{4})-(\d{2})-(\d{2})/','$3/$2/$1',$date).' - '.$titre));
+        saisie_chaine(2, 0, 'Colleur');
+        saisie_chaine(2, 1, utf8_decode('Matière'));
+        saisie_chaine(2, 2, utf8_decode('Élève/Description'));
+        saisie_chaine(2, 3, utf8_decode('Note'));
+        saisie_chaine(2, 4, utf8_decode('Date'));
+        saisie_chaine(2, 5, utf8_decode('Heure'));
+        saisie_chaine(2, 6, utf8_decode('Nb d\'élèves'));
+        saisie_chaine(2, 7, utf8_decode('Durée déclarée'));
+        $i = 2;
+        $n = $hid = 0;
+        while ( $r = $resultat->fetch_assoc() )  {
+          saisie_chaine(++$i, 0, utf8_decode($r['colleur']));
+          saisie_chaine($i, 1, utf8_decode($r['matiere']));
+          if ( strlen($r['eleve']) )  {
+            saisie_chaine($i, 2, utf8_decode($r['eleve']));
+            saisie_chaine($i, 3, utf8_decode($r['note']));
+          }
+          else 
+            saisie_chaine($i, 2, utf8_decode($r['description']));
+          if ( $hid != $r['id'] )  {
+            saisie_chaine($i, 4, utf8_decode($r['jour']));
+            saisie_chaine($i, 5, ( $r['heure'] == '0h00' ) ? '-' : utf8_decode($r['heure']));
+            saisie_chaine($i, 7, format_duree($r['duree']));
+            if ( $n )
+              saisie_nombre($i-$n, 6, $n);
+            $hid = $r['id'];
+            $n = 0;
+          }
+          $n = $n+empty($r['description']);
+        }
+        if ( $n )
+          saisie_nombre($i-$n+1, 6, $n);
+        // Fin du fichier xls
+        echo pack("ss", 0x0A, 0x00);
+        $resultat->free();
+      }
+      exit();
     }
-    // Envoi des headers
-    header("Content-Type: application/vnd.ms-excel");
-    header("Content-Disposition: attachment; filename=decompte-$decompte.xls");
-    header("Content-Transfer-Encoding: binary");
-    // Début du fichier xls
-    echo pack("sssss", 0x809, 6, 0, 0x10, 0);
-    // Remplissage
-    saisie_chaine(0, 0, utf8_decode('Relevé des heures de colles - Détails des notes '.preg_replace('/(\d{4})-(\d{2})-(\d{2})/','$3/$2/$1',$decompte)));
-    saisie_chaine(2, 0, 'Colleur');
-    saisie_chaine(2, 1, utf8_decode('Matière'));
-    saisie_chaine(2, 2, utf8_decode('Élève'));
-    saisie_chaine(2, 3, utf8_decode('Note'));
-    saisie_chaine(2, 4, utf8_decode('Date'));
-    saisie_chaine(2, 5, utf8_decode('Heure'));
-    saisie_chaine(2, 6, utf8_decode('Nb d\'élèves'));
-    saisie_chaine(2, 7, utf8_decode('Durée déclarée'));
-    $i = 2;
-    $n = $hid = 0;
-    while ( $r = $resultat->fetch_assoc() )  {
-      if ( $hid != $r['id'] )  {
-        if ( $n )  {
-          for ( $j = 0 ; $j < $n ; $j++)
-            saisie_nombre($i-$j, 6, $n);
+    case 'impression':  {
+      $date = preg_replace('/(\d{4})-(\d{2})-(\d{2})/','$3/$2/$1',$date);
+      echo <<<FIN
+<!doctype html>
+<html lang="fr">
+<head>
+  <title>Impression</title>
+  <meta charset="utf-8">
+  <link rel="stylesheet" href="css/style1810.min.css">
+</head>
+<body>
+<header>
+  <h1>Relevé des colles - $date - $titre</h1>
+</header>
+
+FIN;
+      // Décompte des heures
+      $resultat = $mysqli->query($requete_decompte);
+      if ( $resultat->num_rows )  {
+        echo "\n  <article>\n    <h3>Relevé des heures, par colleur</h3>\n";
+        echo <<<FIN
+    <table>
+      <tbody>
+        <tr><th>Colleur</th><th>Matière</th><th>Nombre d'élèves</th><th>Séances sans note</th><th>Durée totale déclarée</th></tr>
+FIN;
+        // Remplissage
+        $total_n = $total_duree = $total_duree_td = 0;
+        while ( $r = $resultat->fetch_assoc() )  {
+          echo "\n        <tr><th>${r['colleur']}</th><td>${r['matiere']}</td><td>${r['nb']}</td><td>".format_duree($r['duree_td']).'</td><td>'.format_duree($r['duree']).'</td></tr>';
+          $total_n += $r['nb'];
+          $total_duree_td += $r['duree_td'];
+          $total_duree += $r['duree'];
+        }
+        $resultat->free();
+        echo "\n        <tr><th>Total</th><td></td><td>$total_n</td><td>".format_duree($total_duree_td).'</td><td>'.format_duree($total_duree)."</td></tr>\n      </tbody>\n    </table>\n  </article>\n\n";
+      }
+      
+      // Détail des notes
+      $resultat = $mysqli->query($requete_notes);
+      if ( $resultat->num_rows )  {
+        echo "\n  <article>\n    <h3>Détail des notes</h3>\n";
+        echo <<<FIN
+    <table>
+      <tbody>
+        <tr><th>Colleur</th><th>Matière</th><th colspan="2">Élève et note / Description</th><th>Date</th><th>Heure</th><th>Durée déclarée pour l'heure</th></tr>
+FIN;
+        // Remplissage
+        while ( $r = $resultat->fetch_assoc() )  {
+          $description = ( strlen($r['description']) ? "<td colspan=\"2\">${r['description']}</td>" : "<td>${r['eleve']}</td><td>${r['note']}</td>" );
+          echo "\n        <tr><th>${r['colleur']}</th><td>${r['matiere']}</td>$description<td>${r['jour']}</td><td>".( ( $r['heure'] == '0h00' ) ? '-' : $r['heure'] ).'</td><td>'.format_duree($r['duree']).'</td></tr>';
         }
-        $hid = $r['id'];
-        $n = 0;
+        $resultat->free();
+        echo "\n      </tbody>\n    </table>\n  </article>\n\n";
       }
-      saisie_chaine(++$i, 0, utf8_decode($r['colleur']));
-      saisie_chaine($i, 1, utf8_decode($r['matiere']));
-      saisie_chaine($i, 2, utf8_decode($r['eleve']));
-      saisie_chaine($i, 3, utf8_decode($r['note']));
-      saisie_chaine($i, 4, utf8_decode($r['jour']));
-      saisie_chaine($i, 5, utf8_decode($r['heure']));
-      saisie_chaine($i, 7, format_duree($r['duree']));
-      $n = $n+1;
+      
+      exit("</body>\n</html>\n");
     }
-    for ( $j = 0 ; $j < $n ; $j++)
-      saisie_nombre($i-$j, 6, $n);
-    // Fin du fichier xls
-    echo pack("ss", 0x0A, 0x00);
-    $resultat->free();
-    exit();
   }
 }
 
 //////////////
 //// HTML ////
 //////////////
-debut($mysqli,'Relève des notes de colles',$message,4,'relevenotes');
+debut($mysqli,'Relevé des notes de colles',$message,4,'relevenotes');
 echo <<<FIN
 
   <div id="icones">
@@ -173,11 +237,11 @@
 // Si tableau récapitulatif total demandé
 if ( isset($_REQUEST['tableau']) )  {
   $resultat = $mysqli->query('SELECT IF(LENGTH(c.nom),CONCAT(c.nom,\' \',c.prenom),c.login) AS colleur, m.nom AS matiere, 
-                                     SUM(nb*(releve=0)) AS nbe_nr, SUM(duree*(releve=0)) AS duree_nr, 
-                                     SUM(nb*(releve>0)) AS nbe_r, SUM(duree*(releve>0)) AS duree_r
-                              FROM heurescolles AS h JOIN (SELECT COUNT(*) AS nb, heure FROM notes GROUP BY heure) AS n ON h.id = n.heure
-                                     JOIN utilisateurs AS c ON h.colleur = c.id JOIN matieres AS m ON h.matiere = m.id
-                              GROUP BY h.colleur ORDER BY m.ordre, c.nom');
+                                     SUM(nb*(releve>0)) AS nb_rel, SUM(duree*(releve>0)) AS total_rel, SUM(duree*(releve>0)*(description>\'\')) AS td_rel,
+                                     SUM(nb*(releve=0)) AS nb_nrel, SUM(duree*(releve=0)) AS total_nrel, SUM(duree*(releve=0)*(description>\'\')) AS td_nrel
+                              FROM heurescolles AS h LEFT JOIN utilisateurs AS c ON colleur = c.id LEFT JOIN matieres AS m ON matiere = m.id
+                              LEFT JOIN (SELECT COUNT(*) AS nb, heure FROM notes GROUP BY heure) AS n ON h.id = n.heure
+                              GROUP BY colleur ORDER BY ordre, c.nom');
   echo <<<FIN
   <article>
     <a class="icon-ferme" href="relevenotes" title="Fermer ce récapitulatif"></a>
@@ -188,12 +252,12 @@
     echo <<<FIN
     <table class="centre">
       <tbody>
-        <tr><th colspan="2"></th><th colspan="2">Heures relevées</th><th colspan="2">Heures non relevées</th></tr>
-        <tr><th>Matière</th><th>Colleur</th><th>Nombre d'élèves</th><th>Durée</th><th>Nombre d'élèves</th><th>Durée</th></tr>
+        <tr><th colspan="2"></th><th colspan="3">Heures relevées</th><th colspan="3">Heures non relevées</th></tr>
+        <tr><th>Matière</th><th>Colleur</th><th>Nombre d'élèves</th><th>Séances sans note</th><th>Durée totale</th><th>Nombre d'élèves</th><th>Séances sans note</th><th>Durée totale</th></tr>
 
 FIN;
     while ( $r = $resultat->fetch_assoc() )
-      echo "        <tr><td>${r['matiere']}</td><td>${r['colleur']}</td><td>${r['nbe_nr']}</td><td>".format_duree($r['duree_nr'])."</td><td>${r['nbe_r']}</td><td>".format_duree($r['duree_r'])."</td></tr>\n";
+      echo "        <tr><td>${r['matiere']}</td><td>${r['colleur']}</td><td>${r['nb_rel']}</td><td>".format_duree($r['td_rel']).'</td><td>'.format_duree($r['total_rel'])."</td><td>${r['nb_nrel']}</td><td>".format_duree($r['td_nrel']).'</td><td>'.format_duree($r['total_nrel'])."</td></tr>\n";
     echo "      </tbody>\n    </table>\n  </article>\n\n";
     $resultat->free();
   }
@@ -202,19 +266,19 @@
 }
 
 // Récupération des heures à relever, matière par matière
-$resultat = $mysqli->query('SELECT m.nom AS matiere, SUM(nb) AS nb, SUM(duree) AS duree
-                            FROM heurescolles AS h JOIN (SELECT COUNT(*) AS nb, heure FROM notes GROUP BY heure) AS n ON h.id = n.heure JOIN matieres AS m ON h.matiere = m.id
-                            WHERE h.releve = 0 GROUP BY h.matiere ORDER BY m.ordre');
+$resultat = $mysqli->query('SELECT m.nom AS matiere, SUM(nb) AS nb, SUM(duree*(description>\'\')) AS duree_td, SUM(duree) AS duree
+                            FROM heurescolles AS h LEFT JOIN (SELECT COUNT(*) AS nb, heure FROM notes GROUP BY heure) AS n ON h.id = n.heure LEFT JOIN matieres AS m ON matiere = m.id
+                            WHERE releve = 0 GROUP BY matiere ORDER BY ordre');
 echo "\n  <article>\n    <h3>Heures de colles à relever actuellement</h3>\n";
 if ( $resultat->num_rows )  {
   echo <<<FIN
     <table class="centre">
       <tbody>
-        <tr><th>Matière</th><th>Nombre d'élèves</th><th>Durée</th></tr>
+        <tr><th>Matière</th><th>Nombre d'élèves</th><th>Séances sans note</th><th>Durée totale</th></tr>
 
 FIN;
   while ( $r = $resultat->fetch_assoc() )  {
-    echo "        <tr><td>${r['matiere']}</td><td>${r['nb']}</td><td>".format_duree($r['duree'])."</td></tr>\n";
+    echo "        <tr><td>${r['matiere']}</td><td>${r['nb']}</td><td>".format_duree($r['duree_td']).'</td><td>'.format_duree($r['duree'])."</td></tr>\n";
   }
   echo <<<FIN
       </tbody>
@@ -230,24 +294,24 @@
 
 // Récupération des relevés déjà réalisés
 $resultat = $mysqli->query('SELECT DATE_FORMAT(releve,\'%d/%m/%y\') AS date, DATE_FORMAT(releve,\'%y%m%d\') AS ref, SUM(duree) AS duree, SUM(nb) AS nb
-                            FROM heurescolles AS h JOIN (SELECT COUNT(*) AS nb, heure FROM notes GROUP BY heure) AS n ON h.id = n.heure
+                            FROM heurescolles AS h LEFT JOIN (SELECT COUNT(*) AS nb, heure FROM notes GROUP BY heure) AS n ON h.id = n.heure
                             WHERE releve > 0 GROUP BY releve ORDER BY releve DESC');
 echo "\n  <article>\n    <h3>Relevés déjà réalisés</h3>\n";
 if ( $resultat->num_rows )  {
   echo <<<FIN
     <table class="centre">
       <tbody>
-        <tr><th>Date</th><th>Décomptes des heures</th><th>Détail des notes</th></tr>
+        <tr><th>Date</th><th>Décomptes des heures</th><th>Détail des notes</th><th>Version imprimable</th></tr>
 
 FIN;
   while ( $r = $resultat->fetch_assoc() )  {
-    echo "        <tr><td>${r['date']}</td><td><a class=\"icon-download\" href=\"?decompte=${r['ref']}\"></a> ".format_duree($r['duree'])."</td><td><a class=\"icon-download\" href=\"?notes=${r['ref']}\"></a> ${r['nb']} notes</td></tr>\n";
+    echo "        <tr><td>${r['date']}</td><td><a class=\"icon-download\" href=\"?export=decompte&datereleve=${r['ref']}\"></a>&nbsp;".format_duree($r['duree'])."</td><td><a class=\"icon-download\" href=\"?export=notes&datereleve=${r['ref']}\"></a>&nbsp;${r['nb']} notes</td><td><a class=\"icon-imprime\" onclick=\"printPage('?export=impression&datereleve=${r['ref']}');\"></a></td></tr>\n";
   }
   echo "      </tbody>\n    </table>\n  </article>\n\n";
   $resultat->free();
 }
 else
-  echo "<div class=\"annonce\">Vous n'avez pas encore réalisé de relevé cette année.</div>\n  </article>\n\n";
+  echo "<div class=\"annonce\">Vous n'avez pas encore relevé de colles cette année.</div>\n  </article>\n\n";
 $mysqli->close();
 ?>
 
@@ -257,11 +321,16 @@
     <p>Le bouton <em>Relever les notes</em> permet de réaliser une relève des notes de colles. Cela consiste à marquer comme relevées toutes les heures déclarées jusqu'à maintenant et non encore relevées. Une confirmation sera demandée. Toutes les colles non encore relevées le seront alors&nbsp;: il n'est pas possible de sélectionner seulement une période.</p>
     <p>L'ensemble des relevés est consigné dans un tableau. Y sont téléchargeables&nbsp;:
     <ul>
-      <li>le décompte des heures, suffisant pour mettre au paiement les heures de colles</li>
-      <li>le détail de l'ensemble des notes, si besoin de vérification</li>
-    </ul> 
-    </p>
-    <p>Le bouton général <span class="icon-voirtout"></span> permet de visualiser un tableau récapitulatif global des totaux dans toutes les matières, depuis le début de l'année.</p>
+      <li>le décompte des heures au format xls, suffisant pour mettre au paiement les heures de colles</li>
+      <li>le détail de l'ensemble des notes au format xls, si besoin de vérification</li>
+      <li>l'ensemble des deux documents en format à imprimer, éventuellement en fichier pdf</li>
+    </ul>
+    <p>Les décomptes d'heures contiennent deux types de déclarations&nbsp;:</p>
+    <ul>
+      <li>des colles classiques, avec des notes pour chaque élève ou la mention «&nbsp;Non noté&nbsp;» ou «&nbsp;Absent&nbsp;»</li>
+      <li>des séances sans note, pour payer des séances de cours ou travaux dirigés en heures de colles.</li>
+    </ul>
+    <p>Le bouton général <span class="icon-voirtout"></span> permet de visualiser un tableau récapitulatif global des totaux pour chaque colleur, depuis le début de l'année.</p>
     <h4>Du côté des colleurs</h4>
     <p>Les colleurs et professeurs ne peuvent plus modifier la durée ni le nombre d'élèves notés pendant les colles marquées comme relevées. Ils peuvent cependant encore modifier les notes, y compris pour les élèves «&nbsp;non notés&nbsp;» ou «&nbsp;absents&nbsp;».</p>
     <p>Les colleurs ont accès à la liste de leur colles et des dates de relèves. Ils sont donc au courant des heures qui doivent être mises au paiment.</p>
@@ -274,6 +343,32 @@
     <p>Les élèves absents doivent rattraper leur colle. À défaut, le colleur doit quand même être payé&nbsp;: c'est pour cela qu'il n'y a pas de différence entre un élève noté et un élève absent dans le décompte.</p>
   </div>
 
+  <script type="text/javascript">
+  // Pour l'impression. Récupéré sur https://developer.mozilla.org/en-US/docs/Web/Guide/Printing
+  function closePrint () {
+    document.body.removeChild(this.__container__);
+  }
+  
+  function setPrint () {
+    this.contentWindow.__container__ = this;
+    this.contentWindow.onbeforeunload = closePrint;
+    this.contentWindow.onafterprint = closePrint;
+    this.contentWindow.focus(); // Required for IE
+    this.contentWindow.print();
+  }
+  
+  function printPage (sURL) {
+    var oHiddFrame = document.createElement("iframe");
+    oHiddFrame.onload = setPrint;
+    oHiddFrame.style.visibility = "hidden";
+    oHiddFrame.style.position = "fixed";
+    oHiddFrame.style.right = "0";
+    oHiddFrame.style.bottom = "0";
+    oHiddFrame.src = sURL;
+    document.body.appendChild(oHiddFrame);
+  }
+  </script>
+
   <p id="log"></p>
 
 <?php
