// JS for all ScoDoc pages (using jQuery UI) $(function () { // Autocomplete recherche etudiants par nom $(".in-expnom").autocomplete({ delay: 300, // wait 300ms before suggestions minLength: 2, // min nb of chars before suggest position: { collision: "flip" }, // automatic menu position up/down source: SCO_URL + "/search_etud_by_name", select: function (event, ui) { $(".in-expnom").val(ui.item.value); $("#form-chercheetud").submit(); }, }); // Date picker $(".datepicker").datepicker({ showOn: "button", buttonImage: "/ScoDoc/static/icons/calendar_img.png", buttonImageOnly: true, dateFormat: "dd/mm/yy", duration: "fast", firstDay: 1, // Start with Monday dayNames: [ "Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", ], dayNamesMin: ["Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa"], dayNamesShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"], monthNames: [ "Janvier", "Février", "Mars", "Avril", "May", "Juin", "Juilet", "Août", "Septembre", "Octobre", "Novembre", "Décembre", ], monthNamesShort: [ "Jan", "Fév", "Mar", "Avr", "Mai", "Juin", "Juil", "Aoû", "Sep", "Oct", "Nov", "Déc", ], }); $(".datepicker").datepicker( "option", $.extend({ showMonthAfterYear: false }, $.datepicker.regional["fr"]) ); /* Barre menu */ var sco_menu_position = { my: "left top", at: "left bottom" }; $("#sco_menu") .menu({ position: sco_menu_position, blur: function () { $(this).menu("option", "position", sco_menu_position); }, focus: function (e, ui) { if ($("#sco_menu").get(0) !== $(ui).get(0).item.parent().get(0)) { $(this).menu("option", "position", { my: "left top", at: "right top", }); } }, }) .mouseleave(function (x, y) { $("#sco_menu").menu("collapseAll"); }); $("#sco_menu > li > a > span").switchClass( "ui-icon-carat-1-e", "ui-icon-carat-1-s" ); /* Les menus isoles dropdown */ $(".sco_dropdown_menu") .menu({ position: sco_menu_position, }) .mouseleave(function (x, y) { $(".sco_dropdown_menu").menu("collapseAll"); }); $(".sco_dropdown_menu > li > a > span").switchClass( "ui-icon-carat-1-e", "ui-icon-carat-1-s" ); /* up-to-date status */ var update_div = document.getElementById("update_warning"); if (update_div) { fetch("install_info") .then((response) => response.text()) .then((text) => { update_div.innerHTML = text; if (text) { update_div.style.display = "block"; } }); } }); function sco_capitalize(string) { return string[0].toUpperCase() + string.slice(1).toLowerCase(); } // Affiche un message transitoire (duration milliseconds, 0 means infinity) function sco_message(msg, className = "message_custom", duration = 0) { var div = document.createElement("div"); div.className = className; div.innerHTML = msg; document.querySelector("body").appendChild(div); if (duration) { setTimeout(() => { div.remove(); }, duration); } } function sco_error_message(msg) { sco_message(msg, (className = "message_error"), (duration = 0)); } function get_query_args() { var s = window.location.search; // eg "?x=1&y=2" var vars = {}; s.replace( /[?&]+([^=&]+)=?([^&]*)?/gi, // regexp function (m, key, value) { // callback vars[key] = value !== undefined ? value : ""; } ); return vars; } // Tables (gen_tables) $(function () { if ($("table.gt_table").length > 0) { const url = new URL(document.URL); const order_info_key = JSON.stringify(["table_order", url.pathname]); let order_info; const x = localStorage.getItem(order_info_key); if (x) { try { order_info = JSON.parse(x); } catch (error) { console.error(error); } } var table_options = { paging: false, searching: false, info: false, /* "autoWidth" : false, */ fixedHeader: { header: true, footer: true, }, orderCellsTop: true, // cellules ligne 1 pour tri aaSorting: [], // Prevent initial sorting order: order_info, drawCallback: function (settings) { // permet de conserver l'ordre de tri des colonnes let table = $("table.gt_table").DataTable(); let order_info = JSON.stringify(table.order()); localStorage.setItem(order_info_key, order_info); }, }; $("table.gt_table").DataTable(table_options); table_options["searching"] = true; $("table.gt_table_searchable").DataTable(table_options); } }); // Show tags (readonly) function readOnlyTags(nodes) { // nodes are textareas, hide them and create a span showing tags for (var i = 0; i < nodes.length; i++) { var node = $(nodes[i]); node.hide(); var tags = nodes[i].value.split(","); node.after( '<span class="ro_tags"><span class="ro_tag">' + tags.join('</span><span class="ro_tag">') + "</span></span>" ); } } /* Editeur pour champs * Usage: créer un élément avec data-oid (object id) * La méthode d'URL save sera appelée en POST avec deux arguments: oid et value, * value contenant la valeur du champs. * Inspiré par les codes et conseils de Seb. L. */ class ScoFieldEditor { constructor(selector, save_url, read_only) { this.save_url = save_url; this.read_only = read_only; this.selector = selector; this.installListeners(); } // Enregistre l'élément obj save(obj) { var value = obj.innerText.trim(); if (value.length == 0) { value = ""; } if (value == obj.dataset.value) { return true; // Aucune modification, pas d'enregistrement mais on continue normalement } obj.classList.add("sco_wait"); // DEBUG // console.log(` // data : ${value}, // id: ${obj.dataset.oid} // `); $.post( this.save_url, { oid: obj.dataset.oid, value: value, }, function (result) { obj.classList.remove("sco_wait"); obj.classList.add("sco_modified"); } ); return true; } /*****************************/ /* Gestion des évènements */ /*****************************/ installListeners() { if (this.read_only) { return; } document.body.addEventListener("keydown", this.key); let editor = this; this.handleSelectCell = (event) => { editor.selectCell(event); }; this.handleModifCell = (event) => { editor.modifCell(event); }; this.handleBlur = (event) => { editor.blurCell(event); }; this.handleKeyCell = (event) => { editor.keyCell(event); }; document.querySelectorAll(this.selector).forEach((cellule) => { cellule.addEventListener("click", this.handleSelectCell); cellule.addEventListener("dblclick", this.handleModifCell); cellule.addEventListener("blur", this.handleBlur); }); } /*********************************/ /* Interaction avec les cellules */ /*********************************/ blurCell(event) { let currentModif = document.querySelector(".sco_modifying"); if (currentModif) { if (!this.save(currentModif)) { return; } } } selectCell(event) { let obj = event.currentTarget; if (obj) { if (obj.classList.contains("sco_modifying")) { return; // Cellule en cours de modification, ne pas sélectionner. } let currentModif = document.querySelector(".sco_modifying"); if (currentModif) { if (!this.save(currentModif)) { return; } } this.unselectCell(); obj.classList.add("sco_selected"); } } unselectCell() { document .querySelectorAll(".sco_selected, .sco_modifying") .forEach((cellule) => { cellule.classList.remove("sco_selected", "sco_modifying"); cellule.removeAttribute("contentEditable"); cellule.removeEventListener("keydown", this.handleKeyCell); }); } modifCell(event) { let obj = event.currentTarget; if (obj) { obj.classList.add("sco_modifying"); obj.contentEditable = true; obj.addEventListener("keydown", this.handleKeyCell); obj.focus(); } } key(event) { switch (event.key) { case "Enter": this.modifCell(document.querySelector(".sco_selected")); event.preventDefault(); break; } } keyCell(event) { let obj = event.currentTarget; if (obj) { if (event.key == "Enter") { event.preventDefault(); event.stopPropagation(); if (!this.save(obj)) { return; } obj.classList.remove("sco_modifying"); // ArrowMove(0, 1); // modifCell(document.querySelector(".sco_selected")); this.unselectCell(); } } } } function getCurrentScriptPath() { // Get all the script elements on the page var scripts = document.getElementsByTagName("script"); // Find the last script element (which is the currently executing script) var currentScript = scripts[scripts.length - 1]; // Retrieve the src attribute of the script element var scriptPath = currentScript.src; return scriptPath; } function removeLastTwoComponents(path) { // Split the path into individual components var components = path.split("/"); // Remove the last two components (filename and enclosing directory) components.splice(-2); // Join the remaining components back into a path var newPath = components.join("/"); return newPath; }