Ce script JavaScript s’exécute sur la page moredetail.pl du backoffice de Koha. Il réorganise l'affichage des informations bibliographiques et des exemplaires, améliore la lisibilité, masque certaines données non pertinentes et surligne l'exemplaire correspondant à un code-barres stocké.
moredetail.pl.localStorage..bibliodetails) et les insère dans une section dédiée..page-section et isole ceux qui contiennent des informations d'exemplaire pour les organiser en colonnes (grid)..catalogue-info dans la section des détails bibliographiques tout en évitant les doublons.//mise en page de la page des exemplaires
if (window.location.pathname.includes("moredetail.pl")) {
console.log("Détection de la page 'moredetail.pl'.");
const storedBarcode = localStorage.getItem("searchbox_value");
const catalogueDetail = document.getElementById("catalogue_detail_biblio");
if (!catalogueDetail) {
console.error("Le conteneur principal 'catalogue_detail_biblio' est introuvable.");
return;
}
console.log("Conteneur principal 'catalogue_detail_biblio' trouvé.");
// Création du nouveau conteneur
const newLayout = document.createElement("div");
newLayout.id = "custom-layout";
function createSection(title, content) {
if (!content) {
console.warn(`Contenu introuvable pour la section '${title}'.`);
return null;
}
const section = document.createElement("div");
section.classList.add("custom-section");
section.innerHTML = `<h2>${title}</h2>`;
section.appendChild(content.cloneNode(true));
console.log(`Section '${title}' créée avec succès.`);
return section;
}
const bibliographicDetails = catalogueDetail.querySelector(".listgroup .rows ol.bibliodetails");
if (bibliographicDetails) {
const bibliographicSection = createSection("Informations Bibliographiques", bibliographicDetails);
if (bibliographicSection) newLayout.appendChild(bibliographicSection);
} else {
console.warn("Informations bibliographiques introuvables.");
}
const itemsGrid = document.createElement("div");
itemsGrid.classList.add("items-grid");
const itemSections = catalogueDetail.querySelectorAll(".page-section");
console.log(`Nombre de sections d'exemplaires trouvées : ${itemSections.length}`);
if (itemSections.length > 0) {
let exemplarCount = 1;
itemSections.forEach((section) => {
const itemDetailsHeader = section.querySelector("h4");
if (itemDetailsHeader && itemDetailsHeader.textContent.includes("Information sur l'exemplaire")) {
const itemBlock = document.createElement("div");
itemBlock.classList.add("item-block");
itemBlock.innerHTML = `<h3>Exemplaire ${exemplarCount}</h3>`;
exemplarCount++;
const itemDetails = section.cloneNode(true);
itemBlock.appendChild(itemDetails);
itemsGrid.appendChild(itemBlock);
console.log("Exemplaire ajouté au grid.");
}
});
newLayout.appendChild(itemsGrid);
} else {
console.warn("Aucune section d'exemplaire trouvée.");
}
catalogueDetail.innerHTML = "";
catalogueDetail.appendChild(newLayout);
const style = document.createElement("style");
style.textContent = `
#custom-layout {
display: flex;
flex-direction: column;
gap: 20px;
padding: 10px;
background-color: #f9f9f9;
border: 1px solid #ccc;
}
.custom-section ol li {
list-style: disc;
}
.custom-section ol li span {
font-weight: bold;
}
.custom-section {
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: #fff;
}
.items-grid {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.item-block {
flex: 1 1 calc(33.333% - 20px);
box-sizing: border-box;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: #f1f1f1;
}
.item-block h3 {
margin-top: 0;
}
`;
document.head.appendChild(style);
console.log("Styles personnalisés appliqués.");
function updateLabel(selector, oldText, newText) {
const elements = document.querySelectorAll(selector);
elements.forEach(element => {
if (element.textContent.trim() === oldText) {
element.textContent = newText;
console.log(`Label mis à jour : '${oldText}' → '${newText}'`);
}
});
}
updateLabel("li .label", "Numéro de copie :", "Sous-localisation :");
updateLabel("li .label", "Statut perdu :", "Motif d'exclusion :");
updateLabel("li .label", "Enumération du périodique :", "Etage :");
updateLabel("li .label", "Statut de prêt :", "Informations de prêt :");
const loanStatusElements = document.querySelectorAll("li");
loanStatusElements.forEach(element => {
const loanStatusText = element.innerHTML;
if (loanStatusText.includes("Statut de prêt :")) {
element.innerHTML = loanStatusText.replace(/\s+/g, ' ').replace(/>\s+</g, '><');
console.log("Espaces multiples corrigés dans 'Statut de prêt :'.");
}
});
document.querySelectorAll('ol.bibliodetails > li').forEach(li => {
const textContent = li.textContent.trim();
// Vérifie si le contenu correspond à l'une des valeurs spécifiques
if (
textContent.includes("Coût du prêt") ||
textContent.includes("Coût du prêt par jour") ||
textContent.includes("Frais de location horaires")
) {
li.style.display = "none"; // Masque l'élément
}
});
console.log("Mise en page personnalisée appliquée avec succès.");
if (storedBarcode) {
console.log("Code-barres récupéré dans le localStorage :", storedBarcode);
// Récupérer tous les éléments qui contiennent des codes-barres
const barcodeElements = document.querySelectorAll(".listgroup h3");
console.log(`Nombre d'éléments contenant des codes-barres trouvés : ${barcodeElements.length}`);
barcodeElements.forEach(barcodeElement => {
const barcodeText = barcodeElement.textContent.trim().replace("Code à barres", "").trim();
console.log("Code-barres analysé :", barcodeText);
if (barcodeText === storedBarcode) {
console.log("Code-barres correspondant trouvé :", barcodeText);
const itemBlock = barcodeElement.closest(".item-block");
if (itemBlock) {
itemBlock.style.backgroundColor = "#7abf87"; // Jaune
console.log("Mise en surbrillance appliquée à l'élément.");
} else {
console.warn("Aucun élément 'item-block' associé trouvé.");
}
}
});
function moveCatalogueInfo() {
const catalogueInfo = document.querySelector('.catalogue-info');
if (catalogueInfo) {
// Sélectionner la div 'custom-section' où vous souhaitez insérer 'catalogue-info'
const customSection = document.querySelector('.custom-section');
// Vérifier si la section 'custom-section' existe
if (customSection) {
// Trouver l'élément <ol class="bibliodetails"> à l'intérieur de 'custom-section'
const bibliodetails = customSection.querySelector('ol.bibliodetails');
// Si l'élément <ol class="bibliodetails"> existe, insérer 'catalogue-info' après cette liste
if (bibliodetails) {
// Extraire les types de documents déjà présents dans la liste pour éviter les doublons
const existingDocTypes = Array.from(bibliodetails.querySelectorAll('li span.label'))
.map(span => span.textContent.trim());
// Récupérer les types de documents du 'catalogue-info' et les ajouter un par un
const docTypes = catalogueInfo.querySelectorAll('.doc-type');
docTypes.forEach(docType => {
const typeText = docType.textContent.trim();
// Vérifier si le type de document n'est pas déjà dans la liste
if (!existingDocTypes.includes(typeText)) {
// Créer un nouvel élément <li> pour ce type de document
const newListItem = document.createElement('li');
newListItem.innerHTML = `<span class="label">${typeText} :</span> ${docType.nextElementSibling.textContent.trim()}`;
bibliodetails.appendChild(newListItem); // Ajouter à la liste
existingDocTypes.push(typeText); // Ajouter le type à la liste des existants
}
});
// Déplacer 'catalogue-info' après 'bibliodetails'
customSection.insertBefore(catalogueInfo, bibliodetails.nextSibling);
console.log("Élément déplacé avec succès et types de documents ajoutés.");
} else {
console.log("L'élément <ol class='bibliodetails'> n'a pas été trouvé.");
}
} else {
console.log("Section 'custom-section' non trouvée.");
}
} else {
console.log("Élément 'catalogue-info' non trouvé.");
}
}
// Essayer après un délai de 500ms pour donner le temps aux éléments d'être chargés
setTimeout(moveCatalogueInfo, 500);
} else {
console.warn("Aucun code-barres trouvé dans le localStorage sous 'searchbox_value'.");
}
}
updateLabel() si votre libellé Koha est différent.#7abf87) si vous souhaitez une autre couleur..listgroup ou .page-section change, il faudra adapter les sélecteurs du script.