Compare commits
No commits in common. "ab817e16e1cda991ca8f3cc1b47ddd304fc689fd" and "38c518420300f60376a90d365f1b6912e2c117d8" have entirely different histories.
ab817e16e1
...
38c5184203
|
|
@ -203,8 +203,8 @@ function build_footnotes_index_from_content($content)
|
||||||
}
|
}
|
||||||
|
|
||||||
$footnotes = [];
|
$footnotes = [];
|
||||||
// Trouve les balises <a> avec classe footnote-reference ET attribut data-footnote-content (ordre flexible)
|
// Trouve les balises <a> avec classe footnote-reference ET attribut footnote-content (ordre flexible)
|
||||||
$pattern = '/<a[^>]*class="[^"]*footnote-reference[^"]*"[^>]*data-footnote-content="([^"]*)"[^>]*>|<a[^>]*data-footnote-content="([^"]*)"[^>]*class="[^"]*footnote-reference[^"]*"[^>]*>/i';
|
$pattern = '/<a[^>]*class="[^"]*footnote-reference[^"]*"[^>]*footnote-content="([^"]*)"[^>]*>|<a[^>]*footnote-content="([^"]*)"[^>]*class="[^"]*footnote-reference[^"]*"[^>]*>/i';
|
||||||
$has_footnotes = preg_match_all($pattern, $content, $matches, PREG_SET_ORDER);
|
$has_footnotes = preg_match_all($pattern, $content, $matches, PREG_SET_ORDER);
|
||||||
|
|
||||||
if ($has_footnotes) {
|
if ($has_footnotes) {
|
||||||
|
|
|
||||||
|
|
@ -30,63 +30,16 @@
|
||||||
a.cta--download-pdf {
|
a.cta--download-pdf {
|
||||||
@apply ml-auto;
|
@apply ml-auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#listen-article,
|
|
||||||
#stop-reading {
|
|
||||||
@apply rounded-full w-12 h-12 flex items-center justify-center m-0 p-0 transition-all duration-300;
|
|
||||||
}
|
|
||||||
#listen-article {
|
#listen-article {
|
||||||
@apply bg-primary text-white;
|
@apply bg-primary text-white rounded-full w-12 h-12 flex items-center justify-center m-0 p-0 transition-all duration-300;
|
||||||
&:hover {
|
&:hover {
|
||||||
@apply scale-110;
|
@apply scale-110;
|
||||||
}
|
}
|
||||||
img {
|
img {
|
||||||
@apply w-6 h-6;
|
@apply w-6 h-6;
|
||||||
}
|
}
|
||||||
&[data-reading-status='playing'] {
|
&.is-active {
|
||||||
/* @apply bg-blue-500; */
|
@apply bg-red-500;
|
||||||
@apply bg-white border border-primary;
|
|
||||||
/* &:hover {
|
|
||||||
@apply bg-red-500;
|
|
||||||
} */
|
|
||||||
#play-reading {
|
|
||||||
@apply hidden;
|
|
||||||
}
|
|
||||||
#pause-reading {
|
|
||||||
@apply block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&[data-reading-status='stopped'] {
|
|
||||||
#play-reading {
|
|
||||||
@apply block;
|
|
||||||
}
|
|
||||||
#pause-reading {
|
|
||||||
@apply hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&[data-reading-status='paused'] {
|
|
||||||
@apply bg-yellow-500;
|
|
||||||
#play-reading {
|
|
||||||
@apply block;
|
|
||||||
}
|
|
||||||
#pause-reading {
|
|
||||||
@apply hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#stop-reading {
|
|
||||||
@apply bg-primary hidden;
|
|
||||||
img {
|
|
||||||
@apply w-4 h-4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:has(
|
|
||||||
#listen-article[data-reading-status='playing'],
|
|
||||||
#listen-article[data-reading-status='paused']
|
|
||||||
) {
|
|
||||||
#stop-reading {
|
|
||||||
@apply flex;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
<svg width="16" height="23" viewBox="0 0 16 23" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<g clip-path="url(#clip0_1459_14367)">
|
|
||||||
<path d="M0.941406 0V23" stroke="#136F63" stroke-width="2"/>
|
|
||||||
<path d="M15.0586 0V23" stroke="#136F63" stroke-width="2"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 268 B |
|
|
@ -1,4 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
|
||||||
<rect width="16" height="16" style="fill: #fff;"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 217 B |
|
|
@ -29,4 +29,6 @@ function resetActiveToolbarButtons(): void {
|
||||||
function handleActiveTabContent(tab: string): void {
|
function handleActiveTabContent(tab: string): void {
|
||||||
const contentWrapper = document.querySelector('.content-wrapper');
|
const contentWrapper = document.querySelector('.content-wrapper');
|
||||||
contentWrapper?.setAttribute('data-active-tab', tab);
|
contentWrapper?.setAttribute('data-active-tab', tab);
|
||||||
|
console.log(tab);
|
||||||
|
console.log('contentWrapper');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,65 +1,20 @@
|
||||||
declare var Notyf: any;
|
|
||||||
|
|
||||||
/* ********************************************************
|
|
||||||
* ******************* CONFIGURATION *******************
|
|
||||||
* ********************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
interface ReaderConfig {
|
|
||||||
rate: number;
|
|
||||||
pitch: number;
|
|
||||||
volume: number;
|
|
||||||
highlightColor: string;
|
|
||||||
highlightStyle: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DEFAULT_CONFIG: ReaderConfig = {
|
|
||||||
rate: 1.2,
|
|
||||||
pitch: 1.1,
|
|
||||||
volume: 1,
|
|
||||||
highlightColor: '#f1fcf9',
|
|
||||||
highlightStyle: 'background-color: #136F63; padding: 2px 4px; border-radius: 3px; color:white;',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function handleArticleReader() {
|
export default function handleArticleReader() {
|
||||||
// ✅ DÉCLARATION DES VARIABLES
|
const button = document.getElementById('listen-article');
|
||||||
const playPauseButton = document.getElementById('listen-article');
|
|
||||||
const stopReadingButton = document.getElementById('stop-reading');
|
|
||||||
const article = document.querySelector('.article-content');
|
const article = document.querySelector('.article-content');
|
||||||
|
|
||||||
|
// Paramètres fixes définis dans le code
|
||||||
|
const speechSettings = {
|
||||||
|
rate: 1.2, // Vitesse de lecture (0.1 à 2)
|
||||||
|
pitch: 1.1, // Tonalité (0 à 2)
|
||||||
|
volume: 1, // Volume (0 à 1)
|
||||||
|
};
|
||||||
|
|
||||||
let utterance: SpeechSynthesisUtterance;
|
let utterance: SpeechSynthesisUtterance;
|
||||||
let voices: SpeechSynthesisVoice[] = [];
|
let voices: SpeechSynthesisVoice[] = [];
|
||||||
let thomasVoice: SpeechSynthesisVoice | null = null;
|
let thomasVoice: SpeechSynthesisVoice | null = null;
|
||||||
let currentWordIndex = 0;
|
|
||||||
|
|
||||||
/* ********************************************************
|
|
||||||
* ************** MÉTHODES INTERNES *********************
|
|
||||||
* ********************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Fonctions de gestion du bouton
|
|
||||||
function setReaderButtonReading(): void {
|
|
||||||
if (!playPauseButton) return;
|
|
||||||
playPauseButton.setAttribute('data-reading-status', 'playing');
|
|
||||||
playPauseButton.setAttribute('title', 'Arrêter la lecture vocale');
|
|
||||||
playPauseButton.setAttribute('aria-label', 'Arrêter la lecture vocale');
|
|
||||||
}
|
|
||||||
|
|
||||||
function setReaderButtonStopped(): void {
|
|
||||||
if (!playPauseButton) return;
|
|
||||||
playPauseButton.setAttribute('data-reading-status', 'stopped');
|
|
||||||
playPauseButton.setAttribute('title', "Lancer la lecture vocale de l'article");
|
|
||||||
playPauseButton.setAttribute('aria-label', "Lecture vocale de l'article");
|
|
||||||
}
|
|
||||||
function setReaderButtonPaused(): void {
|
|
||||||
if (!playPauseButton) return;
|
|
||||||
playPauseButton.setAttribute('data-reading-status', 'paused');
|
|
||||||
playPauseButton.setAttribute('title', 'Reprendre la lecture vocale');
|
|
||||||
playPauseButton.setAttribute('aria-label', 'Reprendre la lecture vocale');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Charger les voix et trouver Thomas
|
// Charger les voix et trouver Thomas
|
||||||
function loadVoices(): void {
|
function loadVoices() {
|
||||||
voices = speechSynthesis.getVoices();
|
voices = speechSynthesis.getVoices();
|
||||||
|
|
||||||
// Chercher la voix Thomas (peut être "Thomas" ou contenir "Thomas")
|
// Chercher la voix Thomas (peut être "Thomas" ou contenir "Thomas")
|
||||||
|
|
@ -74,164 +29,76 @@ export default function handleArticleReader() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ HIGHLIGHTING AVANCÉ - Préserve la structure HTML
|
// Charger les voix au démarrage et quand elles changent
|
||||||
let textNodes: Text[] = [];
|
loadVoices();
|
||||||
let wordBoundaries: { node: Text; startOffset: number; endOffset: number; word: string }[] = [];
|
speechSynthesis.onvoiceschanged = loadVoices;
|
||||||
|
|
||||||
function collectTextNodes(element: Element): Text[] {
|
// Variables pour le highlighting
|
||||||
const nodes: Text[] = [];
|
let originalContent = '';
|
||||||
const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, {
|
let words: string[] = [];
|
||||||
acceptNode: (node) => {
|
let currentWordIndex = 0;
|
||||||
// Ignorer les nœuds texte vides ou uniquement des espaces
|
|
||||||
return node.textContent?.trim() ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
let node;
|
function highlightWord(index: number) {
|
||||||
while ((node = walker.nextNode())) {
|
if (!article || index >= words.length) return;
|
||||||
nodes.push(node as Text);
|
|
||||||
|
// Restaurer le contenu original si c'est le premier mot
|
||||||
|
if (index === 0) {
|
||||||
|
article.innerHTML = originalContent;
|
||||||
}
|
}
|
||||||
return nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildWordBoundaries(): void {
|
// Créer le nouveau HTML avec le mot highlighted
|
||||||
wordBoundaries = [];
|
const highlightedWords = words.map((word, i) => {
|
||||||
textNodes = collectTextNodes(article as Element);
|
if (i === index) {
|
||||||
|
return `<span class="speech-highlight" style="background-color: yellow; padding: 2px 4px; border-radius: 3px;">${word}</span>`;
|
||||||
textNodes.forEach((textNode) => {
|
|
||||||
const text = textNode.textContent || '';
|
|
||||||
const wordRegex = /\S+/g; // Mots (non-espaces)
|
|
||||||
let match;
|
|
||||||
|
|
||||||
while ((match = wordRegex.exec(text)) !== null) {
|
|
||||||
wordBoundaries.push({
|
|
||||||
node: textNode,
|
|
||||||
startOffset: match.index,
|
|
||||||
endOffset: match.index + match[0].length,
|
|
||||||
word: match[0],
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
return word;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 🐛 DEBUG: Afficher les mots détectés
|
article.innerHTML = highlightedWords.join(' ');
|
||||||
console.log(
|
|
||||||
'Mots détectés dans le DOM:',
|
|
||||||
wordBoundaries.map((b) => b.word)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function highlightWord(index: number): void {
|
function removeHighlight() {
|
||||||
if (!article || index >= wordBoundaries.length) {
|
if (article && originalContent) {
|
||||||
console.log('❌ Highlight impossible:', { index, totalWords: wordBoundaries.length });
|
article.innerHTML = originalContent;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Supprimer le highlight précédent et reconstruire les boundaries
|
|
||||||
removeHighlight();
|
|
||||||
buildWordBoundaries(); // ✅ Recalculer après cleanup
|
|
||||||
|
|
||||||
// Vérifier à nouveau après reconstruction
|
|
||||||
if (index >= wordBoundaries.length) {
|
|
||||||
console.warn('❌ Index invalide après reconstruction:', {
|
|
||||||
index,
|
|
||||||
totalWords: wordBoundaries.length,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const boundary = wordBoundaries[index];
|
|
||||||
console.log('🎯 Highlighting mot #' + index + ':', boundary.word);
|
|
||||||
|
|
||||||
// Vérifier que le nœud et les offsets sont encore valides
|
|
||||||
if (!boundary.node || !boundary.node.textContent) {
|
|
||||||
console.warn('❌ Nœud texte invalide');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
boundary.startOffset > boundary.node.textContent.length ||
|
|
||||||
boundary.endOffset > boundary.node.textContent.length
|
|
||||||
) {
|
|
||||||
console.warn('❌ Offsets invalides:', {
|
|
||||||
startOffset: boundary.startOffset,
|
|
||||||
endOffset: boundary.endOffset,
|
|
||||||
nodeLength: boundary.node.textContent.length,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const range = document.createRange();
|
|
||||||
range.setStart(boundary.node, boundary.startOffset);
|
|
||||||
range.setEnd(boundary.node, boundary.endOffset);
|
|
||||||
|
|
||||||
// Créer le span de highlight
|
|
||||||
const highlightSpan = document.createElement('span');
|
|
||||||
highlightSpan.className = 'speech-highlight';
|
|
||||||
highlightSpan.style.cssText = DEFAULT_CONFIG.highlightStyle;
|
|
||||||
|
|
||||||
range.surroundContents(highlightSpan);
|
|
||||||
console.log('✅ Highlight réussi pour:', boundary.word);
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('⚠️ Erreur lors du highlight:', error, boundary);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeHighlight(): void {
|
|
||||||
if (!article) return;
|
|
||||||
|
|
||||||
const highlights = article.querySelectorAll('.speech-highlight');
|
|
||||||
highlights.forEach((highlight) => {
|
|
||||||
const parent = highlight.parentNode;
|
|
||||||
if (parent) {
|
|
||||||
// Remplacer le span par son contenu
|
|
||||||
while (highlight.firstChild) {
|
|
||||||
parent.insertBefore(highlight.firstChild, highlight);
|
|
||||||
}
|
|
||||||
parent.removeChild(highlight);
|
|
||||||
|
|
||||||
// Normaliser pour fusionner les nœuds texte adjacents
|
|
||||||
parent.normalize();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Création de l'utterance
|
|
||||||
function createUtterance(text: string): SpeechSynthesisUtterance {
|
function createUtterance(text: string): SpeechSynthesisUtterance {
|
||||||
// ✅ Construire la carte des mots avec leur position dans le DOM
|
// Sauvegarder le contenu original et préparer les mots
|
||||||
buildWordBoundaries();
|
originalContent = article ? article.innerHTML : '';
|
||||||
|
words = text.split(/\s+/).filter((word) => word.trim().length > 0);
|
||||||
currentWordIndex = 0;
|
currentWordIndex = 0;
|
||||||
|
|
||||||
utterance = new SpeechSynthesisUtterance(text);
|
utterance = new SpeechSynthesisUtterance(text);
|
||||||
utterance.lang = 'fr-FR';
|
utterance.lang = 'fr-FR';
|
||||||
|
|
||||||
// Appliquer la configuration
|
// Appliquer les paramètres fixes
|
||||||
utterance.rate = DEFAULT_CONFIG.rate;
|
utterance.rate = speechSettings.rate;
|
||||||
utterance.pitch = DEFAULT_CONFIG.pitch;
|
utterance.pitch = speechSettings.pitch;
|
||||||
utterance.volume = DEFAULT_CONFIG.volume;
|
utterance.volume = speechSettings.volume;
|
||||||
|
|
||||||
// Utiliser Thomas par défaut
|
// Utiliser Thomas par défaut
|
||||||
if (thomasVoice) {
|
if (thomasVoice) {
|
||||||
utterance.voice = thomasVoice;
|
utterance.voice = thomasVoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Event pour highlighter les mots pendant la lecture (basé sur les boundaries DOM)
|
// Event pour highlighter les mots pendant la lecture
|
||||||
utterance.onboundary = (event) => {
|
utterance.onboundary = (event) => {
|
||||||
if (event.name === 'word' && currentWordIndex < wordBoundaries.length) {
|
if (event.name === 'word') {
|
||||||
highlightWord(currentWordIndex);
|
highlightWord(currentWordIndex);
|
||||||
currentWordIndex++;
|
currentWordIndex++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
utterance.onend = () => {
|
utterance.onend = () => {
|
||||||
setReaderButtonStopped();
|
button.textContent = '🔊 Lire en vocal';
|
||||||
removeHighlight();
|
removeHighlight();
|
||||||
currentWordIndex = 0;
|
currentWordIndex = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
utterance.onerror = (event) => {
|
utterance.onerror = (event) => {
|
||||||
console.error('Erreur lors de la lecture:', event);
|
console.error('Erreur lors de la lecture:', event);
|
||||||
setReaderButtonStopped();
|
button.textContent = '🔊 Lire en vocal';
|
||||||
removeHighlight();
|
removeHighlight();
|
||||||
currentWordIndex = 0;
|
currentWordIndex = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -239,105 +106,21 @@ export default function handleArticleReader() {
|
||||||
return utterance;
|
return utterance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fonctions de contrôle de lecture
|
button?.addEventListener('click', () => {
|
||||||
function playReading(): void {
|
|
||||||
if (article) {
|
|
||||||
const text = (article as HTMLElement).innerText.trim();
|
|
||||||
if (text) {
|
|
||||||
createUtterance(text);
|
|
||||||
speechSynthesis.speak(utterance);
|
|
||||||
setReaderButtonReading();
|
|
||||||
showReaderStartedMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function pauseReading(): void {
|
|
||||||
speechSynthesis.pause();
|
|
||||||
setReaderButtonPaused();
|
|
||||||
}
|
|
||||||
|
|
||||||
function stopReading(): void {
|
|
||||||
speechSynthesis.cancel();
|
|
||||||
setReaderButtonStopped();
|
|
||||||
removeHighlight();
|
|
||||||
currentWordIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ********************************************************
|
|
||||||
* *************** INITIALISATION **********************
|
|
||||||
* ********************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Vérifier si la synthèse vocale est déjà en cours au chargement de la page
|
|
||||||
if (speechSynthesis.speaking) {
|
|
||||||
speechSynthesis.cancel();
|
|
||||||
setReaderButtonStopped();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Arrêter la lecture vocale quand l'utilisateur quitte la page
|
|
||||||
window.addEventListener('beforeunload', () => {
|
|
||||||
if (speechSynthesis.speaking) {
|
if (speechSynthesis.speaking) {
|
||||||
speechSynthesis.cancel();
|
speechSynthesis.cancel();
|
||||||
setReaderButtonStopped();
|
button.classList.remove('is-active');
|
||||||
}
|
removeHighlight(); // Retirer le highlight quand on arrête
|
||||||
});
|
currentWordIndex = 0;
|
||||||
|
|
||||||
// Arrêter la lecture vocale quand l'onglet devient invisible
|
|
||||||
document.addEventListener('visibilitychange', () => {
|
|
||||||
if (document.hidden && speechSynthesis.speaking) {
|
|
||||||
speechSynthesis.pause();
|
|
||||||
} else if (!document.hidden && speechSynthesis.paused) {
|
|
||||||
speechSynthesis.resume();
|
|
||||||
setReaderButtonReading();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Charger les voix au démarrage et quand elles changent
|
|
||||||
loadVoices();
|
|
||||||
speechSynthesis.onvoiceschanged = loadVoices;
|
|
||||||
|
|
||||||
// Event listener principal
|
|
||||||
playPauseButton?.addEventListener('click', () => {
|
|
||||||
if (speechSynthesis.speaking && !speechSynthesis.paused) {
|
|
||||||
// En cours de lecture → Pause
|
|
||||||
pauseReading();
|
|
||||||
} else if (speechSynthesis.paused) {
|
|
||||||
// En pause → Reprendre
|
|
||||||
speechSynthesis.resume();
|
|
||||||
setReaderButtonReading();
|
|
||||||
} else {
|
} else {
|
||||||
// Arrêté → Démarrer
|
if (article) {
|
||||||
playReading();
|
const text = (article as HTMLElement).innerText.trim();
|
||||||
|
if (text) {
|
||||||
|
createUtterance(text);
|
||||||
|
speechSynthesis.speak(utterance);
|
||||||
|
button.classList.add('is-active');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
stopReadingButton?.addEventListener('click', () => {
|
|
||||||
stopReading();
|
|
||||||
setReaderButtonStopped();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showReaderStartedMessage() {
|
|
||||||
const notyf = new Notyf({
|
|
||||||
duration: 2000,
|
|
||||||
ripple: false,
|
|
||||||
dismissible: true,
|
|
||||||
types: [
|
|
||||||
{
|
|
||||||
type: 'success',
|
|
||||||
background: '#10B981',
|
|
||||||
icon: {
|
|
||||||
className: 'notyf__icon--success',
|
|
||||||
tagName: 'i',
|
|
||||||
text: '🔊',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
position: {
|
|
||||||
x: 'right',
|
|
||||||
y: 'top',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
notyf.success(`Lecture de l'article lancée !`);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,9 @@ $revueID = get_field('related_revue', get_the_ID());
|
||||||
'ID' => get_the_ID()
|
'ID' => get_the_ID()
|
||||||
)); ?>
|
)); ?>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -47,12 +47,9 @@ $pdf_url = isset($pdf_version) && !empty($pdf_version['url']) ? $pdf_version['ur
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
||||||
<button id="listen-article" type="button" data-reading-status="stopped" title="Lancer la lecture vocale de l'article">
|
<button id="listen-article" type="button">
|
||||||
<img id="play-reading" class="icon" src="<?php echo get_stylesheet_directory_uri(); ?>/resources/img/icons/carhop-ecouter.svg" alt="Lecture vocale de l'article">
|
<img class="icon" src="<?php echo get_stylesheet_directory_uri(); ?>/resources/img/icons/carhop-ecouter.svg" alt="Lecture vocale de l'article">
|
||||||
<img id="pause-reading" class="icon" src="<?php echo get_stylesheet_directory_uri(); ?>/resources/img/icons/carhop-pause.svg" alt="Arrêter la lecture vocale de l'article">
|
|
||||||
</button>
|
|
||||||
<button id="stop-reading" type="button" title="Arrêter la lecture vocale de l'article">
|
|
||||||
<img class="icon" src="<?php echo get_stylesheet_directory_uri(); ?>/resources/img/icons/carhop-stop-reading.svg" alt="Arrêter la lecture vocale de l'article">
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user