2020-09-26 16:19:37 +02:00
|
|
|
// JS for all ScoDoc pages (using jQuery UI)
|
|
|
|
|
2021-02-16 22:07:56 +01:00
|
|
|
$(function () {
|
2023-06-28 21:25:38 +02:00
|
|
|
// 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
|
2024-04-10 18:40:32 +02:00
|
|
|
source: SCO_URL + "search_etud_by_name",
|
2023-06-28 21:25:38 +02:00
|
|
|
select: function (event, ui) {
|
|
|
|
$(".in-expnom").val(ui.item.value);
|
|
|
|
$("#form-chercheetud").submit();
|
|
|
|
},
|
|
|
|
});
|
2021-02-16 22:07:56 +01:00
|
|
|
|
2023-06-28 21:25:38 +02:00
|
|
|
// Date picker
|
|
|
|
$(".datepicker").datepicker({
|
|
|
|
showOn: "button",
|
|
|
|
buttonImage: "/ScoDoc/static/icons/calendar_img.png",
|
|
|
|
buttonImageOnly: true,
|
|
|
|
dateFormat: "dd/mm/yy",
|
|
|
|
duration: "fast",
|
2023-12-01 15:09:27 +01:00
|
|
|
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",
|
2024-01-21 22:21:10 +01:00
|
|
|
"Juillet",
|
2023-12-01 15:09:27 +01:00
|
|
|
"Août",
|
|
|
|
"Septembre",
|
|
|
|
"Octobre",
|
|
|
|
"Novembre",
|
|
|
|
"Décembre",
|
|
|
|
],
|
|
|
|
monthNamesShort: [
|
|
|
|
"Jan",
|
|
|
|
"Fév",
|
|
|
|
"Mar",
|
|
|
|
"Avr",
|
|
|
|
"Mai",
|
|
|
|
"Juin",
|
|
|
|
"Juil",
|
|
|
|
"Aoû",
|
|
|
|
"Sep",
|
|
|
|
"Oct",
|
|
|
|
"Nov",
|
|
|
|
"Déc",
|
|
|
|
],
|
2023-06-28 21:25:38 +02:00
|
|
|
});
|
|
|
|
$(".datepicker").datepicker(
|
|
|
|
"option",
|
|
|
|
$.extend({ showMonthAfterYear: false }, $.datepicker.regional["fr"])
|
|
|
|
);
|
2020-09-26 16:19:37 +02:00
|
|
|
|
2023-06-28 21:25:38 +02:00
|
|
|
/* 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",
|
|
|
|
});
|
2020-09-26 16:19:37 +02:00
|
|
|
}
|
2023-06-28 21:25:38 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
.mouseleave(function (x, y) {
|
|
|
|
$("#sco_menu").menu("collapseAll");
|
2021-02-16 22:07:56 +01:00
|
|
|
});
|
2020-09-26 16:19:37 +02:00
|
|
|
|
2023-06-28 21:25:38 +02:00
|
|
|
$("#sco_menu > li > a > span").switchClass(
|
|
|
|
"ui-icon-carat-1-e",
|
|
|
|
"ui-icon-carat-1-s"
|
|
|
|
);
|
2020-09-26 16:19:37 +02:00
|
|
|
|
2023-06-28 21:25:38 +02:00
|
|
|
/* 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"
|
|
|
|
);
|
2021-02-16 22:07:56 +01:00
|
|
|
|
2023-06-28 21:25:38 +02:00
|
|
|
/* 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";
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2020-09-26 16:19:37 +02:00
|
|
|
});
|
|
|
|
|
2023-06-01 17:58:30 +02:00
|
|
|
function sco_capitalize(string) {
|
2023-06-28 21:25:38 +02:00
|
|
|
return string[0].toUpperCase() + string.slice(1).toLowerCase();
|
2023-06-01 17:58:30 +02:00
|
|
|
}
|
|
|
|
|
2023-05-13 18:35:10 +02:00
|
|
|
// Affiche un message transitoire (duration milliseconds, 0 means infinity)
|
|
|
|
function sco_message(msg, className = "message_custom", duration = 0) {
|
2023-06-28 21:25:38 +02:00
|
|
|
var div = document.createElement("div");
|
|
|
|
div.className = className;
|
|
|
|
div.innerHTML = msg;
|
|
|
|
document.querySelector("body").appendChild(div);
|
|
|
|
if (duration) {
|
|
|
|
setTimeout(() => {
|
|
|
|
div.remove();
|
2023-12-22 15:18:20 +01:00
|
|
|
}, duration);
|
2023-06-28 21:25:38 +02:00
|
|
|
}
|
2020-09-26 16:19:37 +02:00
|
|
|
}
|
|
|
|
|
2023-05-13 18:35:10 +02:00
|
|
|
function sco_error_message(msg) {
|
2023-06-28 21:25:38 +02:00
|
|
|
sco_message(msg, (className = "message_error"), (duration = 0));
|
2023-05-13 18:35:10 +02:00
|
|
|
}
|
2020-09-26 16:19:37 +02:00
|
|
|
|
|
|
|
function get_query_args() {
|
2023-06-28 21:25:38 +02:00
|
|
|
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;
|
2020-09-26 16:19:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Tables (gen_tables)
|
2021-02-16 22:07:56 +01:00
|
|
|
$(function () {
|
2023-06-28 21:25:38 +02:00
|
|
|
if ($("table.gt_table").length > 0) {
|
2023-12-07 19:42:57 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2023-06-28 21:25:38 +02:00
|
|
|
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
|
2023-12-07 19:42:57 +01:00
|
|
|
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);
|
|
|
|
},
|
2023-06-28 21:25:38 +02:00
|
|
|
};
|
|
|
|
$("table.gt_table").DataTable(table_options);
|
|
|
|
table_options["searching"] = true;
|
|
|
|
$("table.gt_table_searchable").DataTable(table_options);
|
|
|
|
}
|
2020-09-26 16:19:37 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
// Show tags (readonly)
|
|
|
|
function readOnlyTags(nodes) {
|
2023-06-28 21:25:38 +02:00
|
|
|
// 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>"
|
|
|
|
);
|
|
|
|
}
|
2020-09-26 16:19:37 +02:00
|
|
|
}
|
2022-04-16 15:34:40 +02:00
|
|
|
|
|
|
|
/* Editeur pour champs
|
|
|
|
* Usage: créer un élément avec data-oid (object id)
|
2023-06-28 21:25:38 +02:00
|
|
|
* La méthode d'URL save sera appelée en POST avec deux arguments: oid et value,
|
2022-04-16 15:34:40 +02:00
|
|
|
* value contenant la valeur du champs.
|
|
|
|
* Inspiré par les codes et conseils de Seb. L.
|
|
|
|
*/
|
|
|
|
class ScoFieldEditor {
|
2023-06-28 21:25:38 +02:00
|
|
|
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 = "";
|
2022-04-16 15:34:40 +02:00
|
|
|
}
|
2023-06-28 21:25:38 +02:00
|
|
|
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}
|
|
|
|
// `);
|
2022-04-16 15:34:40 +02:00
|
|
|
|
2023-06-28 21:25:38 +02:00
|
|
|
$.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;
|
2022-04-16 15:34:40 +02:00
|
|
|
}
|
2023-06-28 21:25:38 +02:00
|
|
|
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;
|
|
|
|
}
|
2022-04-16 15:34:40 +02:00
|
|
|
}
|
2023-06-28 21:25:38 +02:00
|
|
|
}
|
|
|
|
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;
|
2022-04-16 15:34:40 +02:00
|
|
|
}
|
2023-06-28 21:25:38 +02:00
|
|
|
}
|
2022-04-16 15:34:40 +02:00
|
|
|
|
2023-06-28 21:25:38 +02:00
|
|
|
this.unselectCell();
|
|
|
|
obj.classList.add("sco_selected");
|
2022-04-16 15:34:40 +02:00
|
|
|
}
|
2023-06-28 21:25:38 +02:00
|
|
|
}
|
|
|
|
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();
|
2022-04-16 15:34:40 +02:00
|
|
|
}
|
2023-06-28 21:25:38 +02:00
|
|
|
}
|
|
|
|
key(event) {
|
|
|
|
switch (event.key) {
|
|
|
|
case "Enter":
|
|
|
|
this.modifCell(document.querySelector(".sco_selected"));
|
|
|
|
event.preventDefault();
|
|
|
|
break;
|
2022-04-16 15:34:40 +02:00
|
|
|
}
|
2023-06-28 21:25:38 +02:00
|
|
|
}
|
|
|
|
keyCell(event) {
|
|
|
|
let obj = event.currentTarget;
|
|
|
|
if (obj) {
|
|
|
|
if (event.key == "Enter") {
|
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
|
|
|
if (!this.save(obj)) {
|
|
|
|
return;
|
2022-04-16 15:34:40 +02:00
|
|
|
}
|
2023-06-28 21:25:38 +02:00
|
|
|
obj.classList.remove("sco_modifying");
|
|
|
|
// ArrowMove(0, 1);
|
|
|
|
// modifCell(document.querySelector(".sco_selected"));
|
|
|
|
this.unselectCell();
|
|
|
|
}
|
2022-04-16 15:34:40 +02:00
|
|
|
}
|
2023-06-28 21:25:38 +02:00
|
|
|
}
|
2022-04-16 15:34:40 +02:00
|
|
|
}
|
|
|
|
|
2023-05-12 10:00:11 +02:00
|
|
|
function getCurrentScriptPath() {
|
2023-06-28 21:25:38 +02:00
|
|
|
// Get all the script elements on the page
|
|
|
|
var scripts = document.getElementsByTagName("script");
|
2023-05-12 10:00:11 +02:00
|
|
|
|
2023-06-28 21:25:38 +02:00
|
|
|
// Find the last script element (which is the currently executing script)
|
|
|
|
var currentScript = scripts[scripts.length - 1];
|
2023-05-12 10:00:11 +02:00
|
|
|
|
2023-06-28 21:25:38 +02:00
|
|
|
// Retrieve the src attribute of the script element
|
|
|
|
var scriptPath = currentScript.src;
|
2023-05-12 10:00:11 +02:00
|
|
|
|
2023-06-28 21:25:38 +02:00
|
|
|
return scriptPath;
|
2023-05-12 10:00:11 +02:00
|
|
|
}
|
|
|
|
function removeLastTwoComponents(path) {
|
2023-06-28 21:25:38 +02:00
|
|
|
// Split the path into individual components
|
|
|
|
var components = path.split("/");
|
2023-05-12 10:00:11 +02:00
|
|
|
|
2023-06-28 21:25:38 +02:00
|
|
|
// Remove the last two components (filename and enclosing directory)
|
|
|
|
components.splice(-2);
|
2023-05-12 10:00:11 +02:00
|
|
|
|
2023-06-28 21:25:38 +02:00
|
|
|
// Join the remaining components back into a path
|
|
|
|
var newPath = components.join("/");
|
2023-05-12 10:00:11 +02:00
|
|
|
|
2023-06-28 21:25:38 +02:00
|
|
|
return newPath;
|
2023-05-12 10:00:11 +02:00
|
|
|
}
|