265 lines
7.4 KiB
JavaScript
265 lines
7.4 KiB
JavaScript
import { autoResize, creerBlocDOM } from './utils.js';
|
|
|
|
import { activerCollagePropre } from './collagePropre.js';
|
|
import { renderBlocStyle,
|
|
handleSlashCommand,
|
|
handleMarkdownSyntax} from './functionsBloc.js'
|
|
|
|
export function initBlocs() {
|
|
document.querySelectorAll('.editor').forEach(bloc => {
|
|
addBlocEvent(bloc);
|
|
renderBlocStyle(bloc);
|
|
autoResize(bloc);
|
|
activerCollagePropre(bloc);
|
|
});
|
|
|
|
document.querySelectorAll('.editor a').forEach(link => {
|
|
link.addEventListener('click', event => {
|
|
event.preventDefault();
|
|
window.location.href = link.href;
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll('.delete-bloc-btn').forEach(t => {
|
|
addDeleteBloc(t);
|
|
});
|
|
|
|
formatEditorContent();
|
|
|
|
document.querySelectorAll('#md [contenteditable="true"]').forEach(bloc => {
|
|
autoResize(bloc);
|
|
});
|
|
|
|
}
|
|
|
|
function formatEditorContent() {
|
|
document.querySelectorAll('.editor').forEach(function(element) {
|
|
let content = element.innerHTML;
|
|
|
|
content = content.replace(/\n/g, '<br />');
|
|
content = content.replace(/`(.*?)`/g, '<code>$1</code> ');
|
|
content = content.replace(/\*\*(.*?)\*\*/g, '<b>$1</b> ');
|
|
content = content.replace(/\*(.*?)\*/g, '<i>$1</i> ');
|
|
element.innerHTML = content;
|
|
|
|
// Appliquer le rendu MathJax après modification du contenu
|
|
MathJax.typeset();
|
|
autoResize(element);
|
|
});
|
|
}
|
|
|
|
export function addBlocEvent(bloc) {
|
|
bloc.addEventListener('input', event => {
|
|
const blocId = event.target.getAttribute('data-id');
|
|
const content = event.target.innerHTML;
|
|
const type = event.target.getAttribute('data-type');
|
|
const metadata = event.target.getAttribute('data-metadata');
|
|
|
|
const modif = {
|
|
action: "update",
|
|
blocId,
|
|
content,
|
|
metadata,
|
|
type
|
|
};
|
|
|
|
if (window.socketBloc && window.socketBloc.readyState === WebSocket.OPEN) {
|
|
window.socketBloc.send(JSON.stringify(modif));
|
|
}
|
|
});
|
|
|
|
bloc.addEventListener('keydown', async event => {
|
|
if (event.key === 'Enter' && !event.shiftKey) {
|
|
event.preventDefault();
|
|
const texte = bloc.innerText.trim();
|
|
if (texte.startsWith("/")) {
|
|
// Gérer les instructions commençant par /
|
|
await handleSlashCommand(bloc, texte);
|
|
} else {
|
|
// Gérer les titres et citations markdown
|
|
await handleMarkdownSyntax(bloc, texte);
|
|
}
|
|
sauvegarderBloc(bloc);
|
|
ajouterBlocVideSiBesoin();
|
|
formatEditorContent();
|
|
focusDernierBloc();
|
|
|
|
const blocId = bloc.getAttribute('data-id');
|
|
const content = bloc.innerHTML;
|
|
const type = bloc.getAttribute('data-type');
|
|
const classBloc = bloc.getAttribute('class');
|
|
const metadata = bloc.getAttribute('data-metadata');
|
|
const modif = {
|
|
action: "actualiserMiseEnPageBloc",
|
|
blocId,
|
|
content,
|
|
metadata,
|
|
classBloc,
|
|
type
|
|
};
|
|
socketBloc.send(JSON.stringify(modif));
|
|
}
|
|
|
|
// Si on est dans une liste, on crée un nouveau li
|
|
if (event.key === 'Enter' && event.shiftKey) {
|
|
const isListe = bloc.dataset.type === "LISTE";
|
|
if (isListe) {
|
|
event.preventDefault();
|
|
|
|
// Trouver le <li> courant
|
|
const selection = window.getSelection();
|
|
const range = selection.getRangeAt(0);
|
|
const li = (range.startContainer.nodeType === Node.ELEMENT_NODE
|
|
? range.startContainer
|
|
: range.startContainer.parentNode
|
|
).closest('li');
|
|
|
|
if (li) {
|
|
// Créer un nouvel <li> vide
|
|
const newLi = document.createElement('li');
|
|
newLi.innerHTML = '<br>'; // pour que le li soit focusable
|
|
li.parentNode.insertBefore(newLi, li.nextSibling);
|
|
|
|
// Placer le curseur dans le nouveau li
|
|
const newRange = document.createRange();
|
|
newRange.setStart(newLi, 0);
|
|
newRange.collapse(true);
|
|
selection.removeAllRanges();
|
|
selection.addRange(newRange);
|
|
|
|
autoResize(bloc); // redimensionne si nécessaire
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
bloc.addEventListener('input', () => autoResize(bloc));
|
|
}
|
|
|
|
export function sauvegarderBloc(bloc) {
|
|
const blocId = bloc.getAttribute('data-id');
|
|
const type = bloc.getAttribute('data-type');
|
|
const metadata = bloc.getAttribute('data-metadata');
|
|
|
|
const params = new URLSearchParams();
|
|
let contenuTexte = bloc.innerHTML
|
|
.replace(/<br\s*\/?>/gi, '\n')
|
|
.replace(/<b>/gi, '**')
|
|
.replace(/<\/b>/gi, '**')
|
|
.replace(/<i>/gi, '*')
|
|
.replace(/<\/i>/gi, '*')
|
|
.replace(/<code>/gi, '`')
|
|
.replace(/<\/code>/gi, '`')
|
|
.replace(/<\/li>/gi, '\n')
|
|
.replace(/<\/?[^>]+(>|$)/g, ""); // Supprime les balises restantes
|
|
|
|
params.append("contenu", contenuTexte);
|
|
params.append("blocId", blocId);
|
|
params.append("metadata", metadata);
|
|
params.append("type", type);
|
|
|
|
fetch("/Projet/ModifBloc", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
body: params
|
|
}).catch(() => console.error("Erreur lors de la mise à jour du bloc."));
|
|
}
|
|
|
|
export function addDeleteBloc(button) {
|
|
button.addEventListener('click', function() {
|
|
const blocId = button.dataset.id;
|
|
const blocContainer = button.closest('.bloc-container');
|
|
const bloc = blocContainer.querySelector('[contenteditable="true"]');
|
|
|
|
if (bloc.dataset.type != "SEPARATEUR" && bloc.innerText === "") {
|
|
return;
|
|
}
|
|
|
|
if (confirm("Voulez-vous vraiment supprimer ce bloc ?")) {
|
|
const params = new URLSearchParams();
|
|
params.append("blocId", blocId);
|
|
|
|
fetch("/Projet/SupprimerBloc", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
},
|
|
body: params
|
|
}).then(response => {
|
|
if (response.ok) {
|
|
blocContainer.remove();
|
|
ajouterBlocVideSiBesoin();
|
|
|
|
window.socketBloc.send(JSON.stringify({
|
|
action: "deleteBloc",
|
|
blocId,
|
|
}));
|
|
} else {
|
|
console.error("Erreur lors de la suppression du bloc.");
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
export function ajouterBlocVideSiBesoin() {
|
|
const allBlocs = document.querySelectorAll('#md [contenteditable="true"]');
|
|
const pageId = new URLSearchParams(window.location.search).get("id");
|
|
if (pageId === null) return;
|
|
|
|
const message = document.querySelector('.column.is-half p');
|
|
if (message && message.textContent.trim() === "Pas encore de page choisie.") {
|
|
return;
|
|
}
|
|
|
|
if (allBlocs.length === 0 || allBlocs[allBlocs.length - 1].innerText.trim() !== "") {
|
|
const params = new URLSearchParams();
|
|
params.append("contenu", ""); // Bloc vide
|
|
params.append("type", "TEXTE"); // Type par défaut : TEXTE
|
|
params.append("metadata", "{}");
|
|
params.append("ordre", allBlocs.length);
|
|
params.append("pageId", new URLSearchParams(window.location.search).get("id"));
|
|
|
|
fetch("/Projet/NouveauBloc", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
},
|
|
body: params.toString()
|
|
}).then(response => response.json())
|
|
.then(data => {
|
|
if (data && data.idGenere) {
|
|
const idGenere = data.idGenere;
|
|
const newBloc = creerBlocDOM({
|
|
blocId: idGenere,
|
|
content: "",
|
|
type: "TEXTE",
|
|
metadata: "{}",
|
|
ordre: allBlocs.length
|
|
});
|
|
|
|
newBloc.focus();
|
|
|
|
// Envoi d'une notification d'un nouveau bloc créé via websocket
|
|
window.socketBloc.send(JSON.stringify({
|
|
action: "newBloc",
|
|
blocId: idGenere,
|
|
content: "",
|
|
type: "TEXTE",
|
|
metadata: "{}",
|
|
ordre: allBlocs.length
|
|
}));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
export function focusDernierBloc() {
|
|
const blocs = document.querySelectorAll('.editor'); // Remplace `.bloc` par ta classe de bloc
|
|
const dernierBloc = blocs[blocs.length - 1];
|
|
if (dernierBloc) {
|
|
dernierBloc.focus();
|
|
}
|
|
}
|
|
|