diff --git a/app/static/js/saisie_notes.js b/app/static/js/saisie_notes.js
index 3382f0d04fcd2b9268d295b982c6a04f70f76697..1a5eafdb3d9bf46df99e3a106288958437b59c00 100644
--- a/app/static/js/saisie_notes.js
+++ b/app/static/js/saisie_notes.js
@@ -1,17 +1,33 @@
 // Formulaire saisie des notes
 
-$().ready(function () {
-  $("#formnotes .note").bind("blur", valid_note);
+document.addEventListener("DOMContentLoaded", function () {
+  let noteInputs = document.querySelectorAll("#formnotes .note");
+  noteInputs.forEach(function (input) {
+    input.addEventListener("input", function() {
+      this.setAttribute("data-modified", "true");
+    });
+    input.addEventListener("blur", function() {
+      if (this.getAttribute("data-modified") === "true" && this.value !== this.getAttribute("data-last-saved-value")) {
+        valid_note.call(this);
+        this.setAttribute("data-modified", "false"); // Reset the modified flag
+      }
+    });
+  });
+
+  var formInputs = document.querySelectorAll("#formnotes input");
+  formInputs.forEach(function (input) {
+    input.addEventListener("paste", paste_text);
+  });
 
-  $("#formnotes input").bind("paste", paste_text);
-  $(".btn_masquer_DEM").bind("click", masquer_DEM);
+  var masquerBtn = document.querySelector(".btn_masquer_DEM");
+  masquerBtn.addEventListener("click", masquer_DEM);
 });
 
 function is_valid_note(v) {
   if (!v) return true;
 
-  var note_min = parseFloat($("#eval_note_min").text());
-  var note_max = parseFloat($("#eval_note_max").text());
+  var note_min = parseFloat(document.querySelector("#eval_note_min").textContent);
+  var note_max = parseFloat(document.querySelector("#eval_note_max").textContent);
 
   if (!v.match("^-?[0-9]*.?[0-9]*$")) {
     return v == "ABS" || v == "EXC" || v == "SUPR" || v == "ATT" || v == "DEM";
@@ -24,9 +40,9 @@ function is_valid_note(v) {
 function valid_note(e) {
   var v = this.value.trim().toUpperCase().replace(",", ".");
   if (is_valid_note(v)) {
-    if (v && v != $(this).attr("data-last-saved-value")) {
+    if (v && v != this.getAttribute("data-last-saved-value")) {
       this.className = "note_valid_new";
-      const etudid = parseInt($(this).attr("data-etudid"));
+      const etudid = parseInt(this.getAttribute("data-etudid"));
       save_note(this, v, etudid);
     }
   } else {
@@ -36,10 +52,15 @@ function valid_note(e) {
   }
 }
 
+let isSaving = false; // true si requête en cours
+
 async function save_note(elem, v, etudid) {
-  let evaluation_id = $("#formnotes_evaluation_id").attr("value");
-  let formsemestre_id = $("#formnotes_formsemestre_id").attr("value");
-  $("#sco_msg").html("en cours...").show();
+  let evaluation_id = document.querySelector("#formnotes_evaluation_id").getAttribute("value");
+  let formsemestre_id = document.querySelector("#formnotes_formsemestre_id").getAttribute("value");
+  var scoMsg = document.getElementById("sco_msg");
+  scoMsg.innerHTML = "en cours...";
+  scoMsg.style.display = "block";
+  isSaving = true; // Set the flag to true when the request starts
   try {
     const response = await fetch(
       SCO_URL + "../api/evaluation/" + evaluation_id + "/notes/set",
@@ -58,41 +79,62 @@ async function save_note(elem, v, etudid) {
       sco_message("Erreur: valeur non enregistrée");
     } else {
       const data = await response.json();
-      $("#sco_msg").hide();
+      var scoMsg = document.getElementById("sco_msg");
+      scoMsg.style.display = "none";
       if (data.etudids_changed.length > 0) {
         sco_message("enregistré");
         elem.className = "note_saved";
         // Il y avait une decision de jury ?
         if (data.etudids_with_decision.includes(etudid)) {
-          if (v != $(elem).attr("data-orig-value")) {
-            $("#jurylink_" + etudid).html(
-              '<a href="formsemestre_validation_etud_form?formsemestre_id=' +
-                formsemestre_id +
-                "&etudid=" +
-                etudid +
-                '">mettre à jour décision de jury</a>'
-            );
+          if (v !== elem.getAttribute("data-orig-value")) {
+            var juryLink = document.getElementById("jurylink_" + etudid);
+            juryLink.innerHTML = '<a href="formsemestre_validation_etud_form?formsemestre_id=' +
+              formsemestre_id +
+              "&etudid=" +
+              etudid +
+              '">mettre à jour décision de jury</a>';
           } else {
-            $("#jurylink_" + etudid).html("");
+            var juryLink = document.getElementById("jurylink_" + etudid);
+            juryLink.innerHTML = "";
           }
         }
         // Mise à jour menu historique
         if (data.history_menu[etudid]) {
-          $("#hist_" + etudid).html(data.history_menu[etudid]);
+          var historyElem = document.getElementById("hist_" + etudid);
+          historyElem.innerHTML = data.history_menu[etudid];
         }
-        $(elem).attr("data-last-saved-value", v);
+        elem.setAttribute("data-last-saved-value", v);
       }
     }
   } catch (error) {
     console.error("Fetch error:", error);
     sco_message("Erreur réseau: valeur non enregistrée");
+  } finally {
+    isSaving = false; // Reset the flag when the request is complete
   }
 }
 
+// Set up the beforeunload event listener
+window.addEventListener('beforeunload', function (e) {
+  let noteInputs = document.querySelectorAll("#formnotes .note");
+  noteInputs.forEach(function (input) {
+    if (input.getAttribute("data-modified") === "true" && input.value !== input.getAttribute("data-last-saved-value")) {
+      valid_note.call(input);
+    }
+  });
+  if (isSaving) {
+    // Display a confirmation dialog
+    const confirmationMessage = 'Des modifications sont en cours de sauvegarde. Êtes-vous sûr de vouloir quitter cette page ?';
+    e.preventDefault(); // Standard for most modern browsers
+    e.returnValue = confirmationMessage; // For compatibility with older browsers
+    return confirmationMessage; // For compatibility with older browsers
+  }
+});
+
 function change_history(e) {
   let opt = e.selectedOptions[0];
-  let val = $(opt).attr("data-note");
-  const etudid = parseInt($(e).attr("data-etudid"));
+  let val = opt.getAttribute("data-note");
+  const etudid = parseInt(e.getAttribute("data-etudid"));
   // le input associé a ce menu:
   let input_elem = e.parentElement.parentElement.parentElement.childNodes[0];
   input_elem.value = val;
diff --git a/app/templates/babase.j2 b/app/templates/babase.j2
index 63b467264e3329e4d3f14d7226a3dc932c77c13a..b486695357b64f0d555e3b82bc58cf1e0fe2ec66 100644
--- a/app/templates/babase.j2
+++ b/app/templates/babase.j2
@@ -24,6 +24,7 @@
     {% block body -%}
     {% block navbar %}
     {%- endblock navbar %}
+    <div id="sco_msg" class="head_message"></div>
     {% block content -%}
     {%- endblock content %}