@bebranded/bb-contents 1.0.83 → 1.0.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bb-contents.js +336 -361
- package/package.json +1 -1
package/bb-contents.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* BeBranded Contents
|
|
3
3
|
* Contenus additionnels français pour Webflow
|
|
4
|
-
* @version 1.0.
|
|
4
|
+
* @version 1.0.84
|
|
5
5
|
* @author BeBranded
|
|
6
6
|
* @license MIT
|
|
7
7
|
* @website https://www.bebranded.xyz
|
|
@@ -16,30 +16,27 @@
|
|
|
16
16
|
|
|
17
17
|
// Protection contre le double chargement
|
|
18
18
|
if (window.bbContents) {
|
|
19
|
-
console.warn('BeBranded Contents est déjà chargé');
|
|
20
19
|
return;
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
// Vérifier si la version a déjà été affichée
|
|
24
23
|
if (window._bbContentsVersionDisplayed) {
|
|
25
|
-
console.log('🔄 [BB Contents] Version déjà affichée, réinitialisation...');
|
|
26
24
|
return;
|
|
27
25
|
}
|
|
28
26
|
window._bbContentsVersionDisplayed = true;
|
|
29
27
|
|
|
30
28
|
// Protection supplémentaire contre la double initialisation
|
|
31
29
|
if (window._bbContentsInitialized) {
|
|
32
|
-
console.log('🔄 [BB Contents] Déjà initialisé, réinitialisation...');
|
|
33
30
|
return;
|
|
34
31
|
}
|
|
35
32
|
window._bbContentsInitialized = true;
|
|
36
33
|
|
|
37
|
-
// Log de démarrage simple
|
|
38
|
-
console.log('bb-contents | v1.0.
|
|
34
|
+
// Log de démarrage simple (une seule fois)
|
|
35
|
+
console.log('bb-contents | v1.0.84');
|
|
39
36
|
|
|
40
37
|
// Configuration
|
|
41
38
|
const config = {
|
|
42
|
-
version: '1.0.
|
|
39
|
+
version: '1.0.84',
|
|
43
40
|
debug: false, // Debug désactivé pour rendu propre
|
|
44
41
|
prefix: 'bb-', // utilisé pour générer les sélecteurs (data-bb-*)
|
|
45
42
|
youtubeEndpoint: null, // URL du worker YouTube (à définir par l'utilisateur)
|
|
@@ -112,9 +109,7 @@
|
|
|
112
109
|
|
|
113
110
|
// Initialisation
|
|
114
111
|
init: function() {
|
|
115
|
-
//
|
|
116
|
-
console.log('bb-contents | v' + this.config.version);
|
|
117
|
-
|
|
112
|
+
// Initialisation silencieuse
|
|
118
113
|
this.utils.log('Initialisation v' + this.config.version);
|
|
119
114
|
|
|
120
115
|
// Debug environnement supprimé pour console propre
|
|
@@ -263,7 +258,7 @@
|
|
|
263
258
|
if (scope.closest && scope.closest('[data-bb-disable]')) return;
|
|
264
259
|
const elements = scope.querySelectorAll(bbContents._attrSelector('marquee'));
|
|
265
260
|
|
|
266
|
-
|
|
261
|
+
// Éléments marquee détectés
|
|
267
262
|
|
|
268
263
|
// Traitement simple et parallèle de tous les marquees
|
|
269
264
|
elements.forEach((element, index) => {
|
|
@@ -356,7 +351,6 @@
|
|
|
356
351
|
|
|
357
352
|
|
|
358
353
|
if (contentSize === 0) {
|
|
359
|
-
console.log('⚠️ [MARQUEE] Contenu vide, retry dans 200ms');
|
|
360
354
|
setTimeout(() => this.initAnimation(element, scrollContainer, mainBlock, options), 200);
|
|
361
355
|
return;
|
|
362
356
|
}
|
|
@@ -416,12 +410,9 @@
|
|
|
416
410
|
waitTimeout += 100;
|
|
417
411
|
|
|
418
412
|
if (imagesLoaded >= totalImages || imagesLoaded === 0 || waitTimeout >= maxWaitTime) {
|
|
419
|
-
console.log(`✅ [MARQUEE] Safari - Images chargées: ${imagesLoaded}/${totalImages} (timeout: ${waitTimeout}ms)`);
|
|
420
|
-
|
|
421
413
|
// Attendre plus longtemps sur mobile pour le rendu visuel
|
|
422
414
|
const renderDelay = isMobile ? 1000 : 200;
|
|
423
415
|
setTimeout(() => {
|
|
424
|
-
console.log(`🖼️ [MARQUEE] Safari - Attente rendu visuel des images...`);
|
|
425
416
|
startSafariAnimation();
|
|
426
417
|
}, renderDelay);
|
|
427
418
|
} else {
|
|
@@ -434,7 +425,6 @@
|
|
|
434
425
|
const startSafariAnimation = () => {
|
|
435
426
|
// Forcer le chargement des images restantes si timeout
|
|
436
427
|
if (waitTimeout >= maxWaitTime && imagesLoaded < totalImages) {
|
|
437
|
-
console.log(`⚠️ [MARQUEE] Safari - Timeout atteint, forcer chargement images restantes`);
|
|
438
428
|
images.forEach(img => {
|
|
439
429
|
if (img.dataset.src && !img.src) {
|
|
440
430
|
img.src = img.dataset.src;
|
|
@@ -450,11 +440,9 @@
|
|
|
450
440
|
imagesWithSize++;
|
|
451
441
|
}
|
|
452
442
|
});
|
|
453
|
-
console.log(`🖼️ [MARQUEE] Safari - Images avec taille visible: ${imagesWithSize}/${totalImages}`);
|
|
454
443
|
|
|
455
444
|
// Recalculer la taille après chargement des images
|
|
456
445
|
const newContentSize = isVertical ? mainBlock.offsetHeight : mainBlock.offsetWidth;
|
|
457
|
-
console.log(`🔍 [MARQUEE] Safari - Nouvelle taille après images: ${newContentSize}px`);
|
|
458
446
|
|
|
459
447
|
let finalContentSize = newContentSize > contentSize ? newContentSize : contentSize;
|
|
460
448
|
|
|
@@ -467,7 +455,6 @@
|
|
|
467
455
|
if (finalContentSize < 200) {
|
|
468
456
|
// Valeurs par défaut plus généreuses sur mobile
|
|
469
457
|
finalContentSize = isVertical ? (isMobile ? 600 : 400) : (isMobile ? 1000 : 800);
|
|
470
|
-
console.log(`🔍 [MARQUEE] Safari - Utilisation valeur par défaut mobile: ${finalContentSize}px`);
|
|
471
458
|
}
|
|
472
459
|
}
|
|
473
460
|
|
|
@@ -496,8 +483,6 @@
|
|
|
496
483
|
? `translate3d(0, ${currentPosition}px, 0)`
|
|
497
484
|
: `translate3d(${currentPosition}px, 0, 0)`;
|
|
498
485
|
scrollContainer.style.transform = initialTransform;
|
|
499
|
-
|
|
500
|
-
console.log(`🔍 [MARQUEE] Safari - Position initiale: ${currentPosition}px, transform: ${initialTransform}`);
|
|
501
486
|
|
|
502
487
|
// Fonction d'animation Safari avec debug des resets
|
|
503
488
|
let frameCount = 0;
|
|
@@ -508,21 +493,16 @@
|
|
|
508
493
|
if (direction === (isVertical ? 'bottom' : 'right')) {
|
|
509
494
|
currentPosition += step;
|
|
510
495
|
if (currentPosition >= 0) {
|
|
511
|
-
console.log(`🔄 [MARQUEE] Safari RESET bottom/right: ${currentPosition} → ${-(finalContentSize + gapSize)}`);
|
|
512
496
|
currentPosition = -(finalContentSize + gapSize);
|
|
513
497
|
}
|
|
514
498
|
} else {
|
|
515
499
|
currentPosition -= step;
|
|
516
500
|
if (currentPosition <= -(2 * (finalContentSize + gapSize))) {
|
|
517
|
-
console.log(`🔄 [MARQUEE] Safari RESET top/left: ${currentPosition} → ${-(finalContentSize + gapSize)}`);
|
|
518
501
|
currentPosition = -(finalContentSize + gapSize);
|
|
519
502
|
}
|
|
520
503
|
}
|
|
521
504
|
|
|
522
|
-
//
|
|
523
|
-
if (frameCount % 60 === 0) {
|
|
524
|
-
console.log(`📍 [MARQUEE] Safari position: ${currentPosition}px (frame ${frameCount})`);
|
|
525
|
-
}
|
|
505
|
+
// Animation continue
|
|
526
506
|
|
|
527
507
|
// ARRONDI pour éviter les erreurs de précision JavaScript
|
|
528
508
|
currentPosition = Math.round(currentPosition * 100) / 100;
|
|
@@ -539,7 +519,6 @@
|
|
|
539
519
|
// Démarrer l'animation avec un petit délai pour Safari
|
|
540
520
|
setTimeout(() => {
|
|
541
521
|
animate();
|
|
542
|
-
console.log('✅ [MARQUEE] Animation Safari démarrée avec JavaScript optimisé');
|
|
543
522
|
}, 50);
|
|
544
523
|
|
|
545
524
|
// Pause au survol pour Safari
|
|
@@ -599,7 +578,6 @@
|
|
|
599
578
|
|
|
600
579
|
// Démarrer l'animation
|
|
601
580
|
animate();
|
|
602
|
-
console.log('✅ [MARQUEE] Animation standard démarrée');
|
|
603
581
|
|
|
604
582
|
// Pause au survol
|
|
605
583
|
if (pauseOnHover === 'true') {
|
|
@@ -611,261 +589,259 @@
|
|
|
611
589
|
|
|
612
590
|
// Module Share (Partage Social)
|
|
613
591
|
share: {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
},
|
|
621
|
-
facebook: function(data) {
|
|
622
|
-
return 'https://facebook.com/sharer/sharer.php?u=' +
|
|
623
|
-
encodeURIComponent(data.url);
|
|
624
|
-
},
|
|
625
|
-
linkedin: function(data) {
|
|
626
|
-
// LinkedIn - URL de partage officielle (2024+)
|
|
627
|
-
return 'https://www.linkedin.com/sharing/share-offsite/?url=' + encodeURIComponent(data.url);
|
|
628
|
-
},
|
|
629
|
-
whatsapp: function(data) {
|
|
630
|
-
return 'https://wa.me/?text=' +
|
|
631
|
-
encodeURIComponent(data.text + ' ' + data.url);
|
|
632
|
-
},
|
|
633
|
-
telegram: function(data) {
|
|
634
|
-
return 'https://t.me/share/url?url=' +
|
|
635
|
-
encodeURIComponent(data.url) +
|
|
636
|
-
'&text=' + encodeURIComponent(data.text);
|
|
637
|
-
},
|
|
638
|
-
email: function(data) {
|
|
639
|
-
return 'mailto:?subject=' +
|
|
640
|
-
encodeURIComponent(data.text) +
|
|
641
|
-
'&body=' + encodeURIComponent(data.text + ' ' + data.url);
|
|
642
|
-
},
|
|
643
|
-
copy: function(data) {
|
|
644
|
-
return 'copy:' + data.url;
|
|
645
|
-
},
|
|
646
|
-
native: function(data) {
|
|
647
|
-
return 'native:' + JSON.stringify(data);
|
|
648
|
-
}
|
|
592
|
+
// Configuration des réseaux
|
|
593
|
+
networks: {
|
|
594
|
+
twitter: function(data) {
|
|
595
|
+
return 'https://twitter.com/intent/tweet?url=' +
|
|
596
|
+
encodeURIComponent(data.url) +
|
|
597
|
+
'&text=' + encodeURIComponent(data.text);
|
|
649
598
|
},
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
const s = scope || document;
|
|
654
|
-
return s.querySelector(bbContents._attrSelector('share')) !== null;
|
|
599
|
+
facebook: function(data) {
|
|
600
|
+
return 'https://facebook.com/sharer/sharer.php?u=' +
|
|
601
|
+
encodeURIComponent(data.url);
|
|
655
602
|
},
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
// Récupérer les données
|
|
669
|
-
const network = bbContents._getAttr(element, 'bb-share');
|
|
670
|
-
const customUrl = bbContents._getAttr(element, 'bb-url');
|
|
671
|
-
const customText = bbContents._getAttr(element, 'bb-text');
|
|
672
|
-
|
|
673
|
-
// Valeurs par défaut sécurisées
|
|
674
|
-
const data = {
|
|
675
|
-
url: bbContents.utils.isValidUrl(customUrl) ? customUrl : window.location.href,
|
|
676
|
-
text: bbContents.utils.sanitize(customText || document.title || 'Découvrez ce site')
|
|
677
|
-
};
|
|
678
|
-
|
|
679
|
-
// Gestionnaire de clic
|
|
680
|
-
element.addEventListener('click', function(e) {
|
|
681
|
-
e.preventDefault();
|
|
682
|
-
bbContents.modules.share.share(network, data, element);
|
|
683
|
-
});
|
|
684
|
-
|
|
685
|
-
// Accessibilité
|
|
686
|
-
if (element.tagName !== 'BUTTON' && element.tagName !== 'A') {
|
|
687
|
-
element.setAttribute('role', 'button');
|
|
688
|
-
element.setAttribute('tabindex', '0');
|
|
689
|
-
|
|
690
|
-
// Support clavier
|
|
691
|
-
element.addEventListener('keydown', function(e) {
|
|
692
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
693
|
-
e.preventDefault();
|
|
694
|
-
bbContents.modules.share.share(network, data, element);
|
|
695
|
-
}
|
|
696
|
-
});
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
element.style.cursor = 'pointer';
|
|
700
|
-
});
|
|
701
|
-
|
|
702
|
-
bbContents.utils.log('Module Share initialisé:', elements.length, 'éléments');
|
|
603
|
+
linkedin: function(data) {
|
|
604
|
+
// LinkedIn - URL de partage officielle (2024+)
|
|
605
|
+
return 'https://www.linkedin.com/sharing/share-offsite/?url=' + encodeURIComponent(data.url);
|
|
606
|
+
},
|
|
607
|
+
whatsapp: function(data) {
|
|
608
|
+
return 'https://wa.me/?text=' +
|
|
609
|
+
encodeURIComponent(data.text + ' ' + data.url);
|
|
610
|
+
},
|
|
611
|
+
telegram: function(data) {
|
|
612
|
+
return 'https://t.me/share/url?url=' +
|
|
613
|
+
encodeURIComponent(data.url) +
|
|
614
|
+
'&text=' + encodeURIComponent(data.text);
|
|
703
615
|
},
|
|
616
|
+
email: function(data) {
|
|
617
|
+
return 'mailto:?subject=' +
|
|
618
|
+
encodeURIComponent(data.text) +
|
|
619
|
+
'&body=' + encodeURIComponent(data.text + ' ' + data.url);
|
|
620
|
+
},
|
|
621
|
+
copy: function(data) {
|
|
622
|
+
return 'copy:' + data.url;
|
|
623
|
+
},
|
|
624
|
+
native: function(data) {
|
|
625
|
+
return 'native:' + JSON.stringify(data);
|
|
626
|
+
}
|
|
627
|
+
},
|
|
628
|
+
|
|
629
|
+
// Détection
|
|
630
|
+
detect: function(scope) {
|
|
631
|
+
const s = scope || document;
|
|
632
|
+
return s.querySelector(bbContents._attrSelector('share')) !== null;
|
|
633
|
+
},
|
|
634
|
+
|
|
635
|
+
// Initialisation
|
|
636
|
+
init: function(root) {
|
|
637
|
+
const scope = root || document;
|
|
638
|
+
if (scope.closest && scope.closest('[data-bb-disable]')) return;
|
|
639
|
+
const elements = scope.querySelectorAll(bbContents._attrSelector('share'));
|
|
704
640
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
if (!networkFunc) {
|
|
710
|
-
console.error('[BB Contents] Réseau non supporté:', network);
|
|
711
|
-
return;
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
const shareUrl = networkFunc(data);
|
|
715
|
-
|
|
716
|
-
// Cas spécial : copier le lien
|
|
717
|
-
if (shareUrl.startsWith('copy:')) {
|
|
718
|
-
const url = shareUrl.substring(5);
|
|
719
|
-
// Copie silencieuse (pas de feedback visuel)
|
|
720
|
-
this.copyToClipboard(url, element, true);
|
|
721
|
-
return;
|
|
722
|
-
}
|
|
641
|
+
elements.forEach(function(element) {
|
|
642
|
+
// Vérifier si déjà traité
|
|
643
|
+
if (element.bbProcessed) return;
|
|
644
|
+
element.bbProcessed = true;
|
|
723
645
|
|
|
724
|
-
//
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
return;
|
|
729
|
-
}
|
|
646
|
+
// Récupérer les données
|
|
647
|
+
const network = bbContents._getAttr(element, 'bb-share');
|
|
648
|
+
const customUrl = bbContents._getAttr(element, 'bb-url');
|
|
649
|
+
const customText = bbContents._getAttr(element, 'bb-text');
|
|
730
650
|
|
|
731
|
-
//
|
|
732
|
-
const
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
651
|
+
// Valeurs par défaut sécurisées
|
|
652
|
+
const data = {
|
|
653
|
+
url: bbContents.utils.isValidUrl(customUrl) ? customUrl : window.location.href,
|
|
654
|
+
text: bbContents.utils.sanitize(customText || document.title || 'Découvrez ce site')
|
|
655
|
+
};
|
|
736
656
|
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
);
|
|
657
|
+
// Gestionnaire de clic
|
|
658
|
+
element.addEventListener('click', function(e) {
|
|
659
|
+
e.preventDefault();
|
|
660
|
+
bbContents.modules.share.share(network, data, element);
|
|
661
|
+
});
|
|
742
662
|
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
bbContents.modules.share.showFeedback(element, '✓ ' + (bbContents.config.i18n.copied || 'Lien copié !'));
|
|
663
|
+
// Accessibilité
|
|
664
|
+
if (element.tagName !== 'BUTTON' && element.tagName !== 'A') {
|
|
665
|
+
element.setAttribute('role', 'button');
|
|
666
|
+
element.setAttribute('tabindex', '0');
|
|
667
|
+
|
|
668
|
+
// Support clavier
|
|
669
|
+
element.addEventListener('keydown', function(e) {
|
|
670
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
671
|
+
e.preventDefault();
|
|
672
|
+
bbContents.modules.share.share(network, data, element);
|
|
754
673
|
}
|
|
755
|
-
}).catch(function() {
|
|
756
|
-
bbContents.modules.share.fallbackCopy(text, element, isSilent);
|
|
757
674
|
});
|
|
758
|
-
} else {
|
|
759
|
-
// Fallback pour environnements sans Clipboard API
|
|
760
|
-
this.fallbackCopy(text, element, isSilent);
|
|
761
675
|
}
|
|
762
|
-
|
|
676
|
+
|
|
677
|
+
element.style.cursor = 'pointer';
|
|
678
|
+
});
|
|
763
679
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
// Afficher un prompt natif pour permettre à l'utilisateur de copier manuellement
|
|
771
|
-
// (solution universelle sans execCommand)
|
|
772
|
-
window.prompt('Copiez le lien ci-dessous (Ctrl/Cmd+C) :', text);
|
|
773
|
-
} catch (err) {
|
|
774
|
-
// Dernier recours: ne rien faire
|
|
775
|
-
}
|
|
776
|
-
},
|
|
680
|
+
bbContents.utils.log('Module Share initialisé:', elements.length, 'éléments');
|
|
681
|
+
},
|
|
682
|
+
|
|
683
|
+
// Fonction de partage
|
|
684
|
+
share: function(network, data, element) {
|
|
685
|
+
const networkFunc = this.networks[network];
|
|
777
686
|
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
if (navigator.share) {
|
|
782
|
-
navigator.share({
|
|
783
|
-
title: data.text,
|
|
784
|
-
url: data.url
|
|
785
|
-
}).then(function() {
|
|
786
|
-
bbContents.utils.log('Partage natif réussi');
|
|
787
|
-
}).catch(function(error) {
|
|
788
|
-
if (error.name !== 'AbortError') {
|
|
789
|
-
console.error('[BB Contents] Erreur partage natif:', error);
|
|
790
|
-
// Fallback vers copie si échec
|
|
791
|
-
bbContents.modules.share.copyToClipboard(data.url, element, false);
|
|
792
|
-
}
|
|
793
|
-
});
|
|
794
|
-
} else {
|
|
795
|
-
// Fallback si Web Share API non disponible
|
|
796
|
-
bbContents.utils.log('Web Share API non disponible, fallback vers copie');
|
|
797
|
-
this.copyToClipboard(data.url, element, false);
|
|
798
|
-
}
|
|
799
|
-
},
|
|
687
|
+
if (!networkFunc) {
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
800
690
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
691
|
+
const shareUrl = networkFunc(data);
|
|
692
|
+
|
|
693
|
+
// Cas spécial : copier le lien
|
|
694
|
+
if (shareUrl.startsWith('copy:')) {
|
|
695
|
+
const url = shareUrl.substring(5);
|
|
696
|
+
// Copie silencieuse (pas de feedback visuel)
|
|
697
|
+
this.copyToClipboard(url, element, true);
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// Cas spécial : partage natif (Web Share API)
|
|
702
|
+
if (shareUrl.startsWith('native:')) {
|
|
703
|
+
const shareData = JSON.parse(shareUrl.substring(7));
|
|
704
|
+
this.nativeShare(shareData, element);
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// Ouvrir popup de partage
|
|
709
|
+
const width = 600;
|
|
710
|
+
const height = 400;
|
|
711
|
+
const left = (window.innerWidth - width) / 2;
|
|
712
|
+
const top = (window.innerHeight - height) / 2;
|
|
713
|
+
|
|
714
|
+
window.open(
|
|
715
|
+
shareUrl,
|
|
716
|
+
'bbshare',
|
|
717
|
+
'width=' + width + ',height=' + height + ',left=' + left + ',top=' + top + ',noopener,noreferrer'
|
|
718
|
+
);
|
|
719
|
+
|
|
720
|
+
bbContents.utils.log('Partage sur', network, data);
|
|
721
|
+
},
|
|
722
|
+
|
|
723
|
+
// Copier dans le presse-papier
|
|
724
|
+
copyToClipboard: function(text, element, silent) {
|
|
725
|
+
const isSilent = !!silent;
|
|
726
|
+
// Méthode moderne
|
|
727
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
728
|
+
navigator.clipboard.writeText(text).then(function() {
|
|
729
|
+
if (!isSilent) {
|
|
730
|
+
bbContents.modules.share.showFeedback(element, '✓ ' + (bbContents.config.i18n.copied || 'Lien copié !'));
|
|
731
|
+
}
|
|
732
|
+
}).catch(function() {
|
|
733
|
+
bbContents.modules.share.fallbackCopy(text, element, isSilent);
|
|
734
|
+
});
|
|
735
|
+
} else {
|
|
736
|
+
// Fallback pour environnements sans Clipboard API
|
|
737
|
+
this.fallbackCopy(text, element, isSilent);
|
|
738
|
+
}
|
|
739
|
+
},
|
|
740
|
+
|
|
741
|
+
// Fallback copie
|
|
742
|
+
fallbackCopy: function(text, element, silent) {
|
|
743
|
+
const isSilent = !!silent;
|
|
744
|
+
// Pas de UI si silencieux (exigence produit)
|
|
745
|
+
if (isSilent) return;
|
|
746
|
+
try {
|
|
747
|
+
// Afficher un prompt natif pour permettre à l'utilisateur de copier manuellement
|
|
748
|
+
// (solution universelle sans execCommand)
|
|
749
|
+
window.prompt('Copiez le lien ci-dessous (Ctrl/Cmd+C) :', text);
|
|
750
|
+
} catch (err) {
|
|
751
|
+
// Dernier recours: ne rien faire
|
|
752
|
+
}
|
|
753
|
+
},
|
|
754
|
+
|
|
755
|
+
// Partage natif (Web Share API)
|
|
756
|
+
nativeShare: function(data, element) {
|
|
757
|
+
// Vérifier si Web Share API est disponible
|
|
758
|
+
if (navigator.share) {
|
|
759
|
+
navigator.share({
|
|
760
|
+
title: data.text,
|
|
761
|
+
url: data.url
|
|
762
|
+
}).then(function() {
|
|
763
|
+
bbContents.utils.log('Partage natif réussi');
|
|
764
|
+
}).catch(function(error) {
|
|
765
|
+
if (error.name !== 'AbortError') {
|
|
766
|
+
// Fallback vers copie si échec
|
|
767
|
+
bbContents.modules.share.copyToClipboard(data.url, element, false);
|
|
768
|
+
}
|
|
769
|
+
});
|
|
770
|
+
} else {
|
|
771
|
+
// Fallback si Web Share API non disponible
|
|
772
|
+
bbContents.utils.log('Web Share API non disponible, fallback vers copie');
|
|
773
|
+
this.copyToClipboard(data.url, element, false);
|
|
811
774
|
}
|
|
812
775
|
},
|
|
776
|
+
|
|
777
|
+
// Feedback visuel
|
|
778
|
+
showFeedback: function(element, message) {
|
|
779
|
+
const originalText = element.textContent;
|
|
780
|
+
element.textContent = message;
|
|
781
|
+
element.style.pointerEvents = 'none';
|
|
782
|
+
|
|
783
|
+
setTimeout(function() {
|
|
784
|
+
element.textContent = originalText;
|
|
785
|
+
element.style.pointerEvents = '';
|
|
786
|
+
}, 2000);
|
|
787
|
+
}
|
|
788
|
+
},
|
|
813
789
|
|
|
814
790
|
// Module Current Year (Année courante)
|
|
815
791
|
currentYear: {
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
792
|
+
detect: function(scope) {
|
|
793
|
+
const s = scope || document;
|
|
794
|
+
return s.querySelector(bbContents._attrSelector('current-year')) !== null;
|
|
795
|
+
},
|
|
796
|
+
init: function(root) {
|
|
797
|
+
const scope = root || document;
|
|
798
|
+
if (scope.closest && scope.closest('[data-bb-disable]')) return;
|
|
799
|
+
const elements = scope.querySelectorAll(bbContents._attrSelector('current-year'));
|
|
824
800
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
801
|
+
const year = String(new Date().getFullYear());
|
|
802
|
+
elements.forEach(function(element) {
|
|
803
|
+
if (element.bbProcessed) return;
|
|
804
|
+
element.bbProcessed = true;
|
|
829
805
|
|
|
830
806
|
const customFormat = bbContents._getAttr(element, 'bb-current-year-format');
|
|
831
807
|
const prefix = bbContents._getAttr(element, 'bb-current-year-prefix');
|
|
832
808
|
const suffix = bbContents._getAttr(element, 'bb-current-year-suffix');
|
|
833
809
|
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
810
|
+
if (customFormat && customFormat.includes('{year}')) {
|
|
811
|
+
element.textContent = customFormat.replace('{year}', year);
|
|
812
|
+
} else if (prefix || suffix) {
|
|
813
|
+
element.textContent = prefix + year + suffix;
|
|
814
|
+
} else {
|
|
815
|
+
element.textContent = year;
|
|
816
|
+
}
|
|
817
|
+
});
|
|
842
818
|
|
|
843
|
-
|
|
844
|
-
|
|
819
|
+
bbContents.utils.log('Module CurrentYear initialisé:', elements.length, 'éléments');
|
|
820
|
+
}
|
|
845
821
|
},
|
|
846
822
|
|
|
847
823
|
// Module Reading Time (Temps de lecture)
|
|
848
824
|
readingTime: {
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
825
|
+
detect: function(scope) {
|
|
826
|
+
const s = scope || document;
|
|
827
|
+
return s.querySelector(bbContents._attrSelector('reading-time')) !== null;
|
|
828
|
+
},
|
|
829
|
+
init: function(root) {
|
|
830
|
+
const scope = root || document;
|
|
831
|
+
if (scope.closest && scope.closest('[data-bb-disable]')) return;
|
|
832
|
+
const elements = scope.querySelectorAll(bbContents._attrSelector('reading-time'));
|
|
857
833
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
834
|
+
elements.forEach(function(element) {
|
|
835
|
+
if (element.bbProcessed) return;
|
|
836
|
+
element.bbProcessed = true;
|
|
861
837
|
|
|
862
838
|
const targetSelector = bbContents._getAttr(element, 'bb-reading-time-target');
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
839
|
+
const speedAttr = bbContents._getAttr(element, 'bb-reading-time-speed');
|
|
840
|
+
const imageSpeedAttr = bbContents._getAttr(element, 'bb-reading-time-image-speed');
|
|
841
|
+
const format = bbContents._getAttr(element, 'bb-reading-time-format') || '{minutes} min';
|
|
866
842
|
|
|
867
|
-
|
|
868
|
-
|
|
843
|
+
const wordsPerMinute = Number(speedAttr) > 0 ? Number(speedAttr) : 230;
|
|
844
|
+
const secondsPerImage = Number(imageSpeedAttr) > 0 ? Number(imageSpeedAttr) : 12;
|
|
869
845
|
|
|
870
846
|
// Validation des valeurs
|
|
871
847
|
if (isNaN(wordsPerMinute) || wordsPerMinute <= 0) {
|
|
@@ -875,125 +851,125 @@
|
|
|
875
851
|
bbContents.utils.log('Temps par image invalide, utilisation de la valeur par défaut (12)');
|
|
876
852
|
}
|
|
877
853
|
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
854
|
+
let sourceNode = element;
|
|
855
|
+
if (targetSelector) {
|
|
856
|
+
const found = document.querySelector(targetSelector);
|
|
857
|
+
if (found) sourceNode = found;
|
|
858
|
+
}
|
|
883
859
|
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
860
|
+
const text = (sourceNode.textContent || '').trim();
|
|
861
|
+
const wordCount = text ? (text.match(/\b\w+\b/g) || []).length : 0;
|
|
862
|
+
|
|
863
|
+
// Compter les images dans le contenu ciblé
|
|
864
|
+
const images = sourceNode.querySelectorAll('img');
|
|
865
|
+
const imageCount = images.length;
|
|
866
|
+
const imageTimeInMinutes = (imageCount * secondsPerImage) / 60;
|
|
867
|
+
|
|
868
|
+
let minutesFloat = (wordCount / wordsPerMinute) + imageTimeInMinutes;
|
|
869
|
+
let minutes = Math.ceil(minutesFloat);
|
|
894
870
|
|
|
895
|
-
|
|
896
|
-
|
|
871
|
+
if ((wordCount > 0 || imageCount > 0) && minutes < 1) minutes = 1; // affichage minimal 1 min si contenu non vide
|
|
872
|
+
if (wordCount === 0 && imageCount === 0) minutes = 0;
|
|
897
873
|
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
874
|
+
const output = format.replace('{minutes}', String(minutes));
|
|
875
|
+
element.textContent = output;
|
|
876
|
+
});
|
|
901
877
|
|
|
902
|
-
|
|
903
|
-
|
|
878
|
+
bbContents.utils.log('Module ReadingTime initialisé:', elements.length, 'éléments');
|
|
879
|
+
}
|
|
904
880
|
},
|
|
905
881
|
|
|
906
882
|
// Module Favicon (Favicon Dynamique)
|
|
907
883
|
favicon: {
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
884
|
+
originalFavicon: null,
|
|
885
|
+
|
|
886
|
+
// Détection
|
|
887
|
+
detect: function(scope) {
|
|
888
|
+
const s = scope || document;
|
|
889
|
+
return s.querySelector(bbContents._attrSelector('favicon')) !== null;
|
|
890
|
+
},
|
|
891
|
+
|
|
892
|
+
// Initialisation
|
|
893
|
+
init: function(root) {
|
|
894
|
+
const scope = root || document;
|
|
895
|
+
if (scope.closest && scope.closest('[data-bb-disable]')) return;
|
|
915
896
|
|
|
916
|
-
//
|
|
917
|
-
init: function(root) {
|
|
918
|
-
const scope = root || document;
|
|
919
|
-
if (scope.closest && scope.closest('[data-bb-disable]')) return;
|
|
920
|
-
|
|
921
|
-
// Chercher les éléments avec bb-favicon ou bb-favicon-dark
|
|
897
|
+
// Chercher les éléments avec bb-favicon ou bb-favicon-dark
|
|
922
898
|
const elements = scope.querySelectorAll(bbContents._attrSelector('favicon') + ', ' + bbContents._attrSelector('favicon-dark'));
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
// Sauvegarder le favicon original
|
|
926
|
-
const existingLink = document.querySelector("link[rel*='icon']");
|
|
927
|
-
if (existingLink) {
|
|
928
|
-
this.originalFavicon = existingLink.href;
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
// Collecter les URLs depuis tous les éléments
|
|
932
|
-
let faviconUrl = null;
|
|
933
|
-
let darkUrl = null;
|
|
934
|
-
|
|
935
|
-
elements.forEach(function(element) {
|
|
936
|
-
const light = bbContents._getAttr(element, 'bb-favicon') || bbContents._getAttr(element, 'favicon');
|
|
937
|
-
const dark = bbContents._getAttr(element, 'bb-favicon-dark') || bbContents._getAttr(element, 'favicon-dark');
|
|
938
|
-
|
|
939
|
-
if (light) faviconUrl = light;
|
|
940
|
-
if (dark) darkUrl = dark;
|
|
941
|
-
});
|
|
942
|
-
|
|
943
|
-
// Appliquer la logique
|
|
944
|
-
if (faviconUrl && darkUrl) {
|
|
945
|
-
this.setupDarkMode(faviconUrl, darkUrl);
|
|
946
|
-
} else if (faviconUrl) {
|
|
947
|
-
this.setFavicon(faviconUrl);
|
|
948
|
-
bbContents.utils.log('Favicon changé:', faviconUrl);
|
|
949
|
-
}
|
|
950
|
-
},
|
|
899
|
+
if (elements.length === 0) return;
|
|
951
900
|
|
|
952
|
-
//
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
favicon = document.createElement('link');
|
|
958
|
-
favicon.rel = 'icon';
|
|
959
|
-
document.head.appendChild(favicon);
|
|
960
|
-
}
|
|
961
|
-
return favicon;
|
|
962
|
-
},
|
|
901
|
+
// Sauvegarder le favicon original
|
|
902
|
+
const existingLink = document.querySelector("link[rel*='icon']");
|
|
903
|
+
if (existingLink) {
|
|
904
|
+
this.originalFavicon = existingLink.href;
|
|
905
|
+
}
|
|
963
906
|
|
|
964
|
-
//
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
// Ajouter un timestamp pour forcer le rafraîchissement du cache
|
|
969
|
-
const cacheBuster = '?v=' + Date.now();
|
|
970
|
-
const urlWithCacheBuster = url + cacheBuster;
|
|
971
|
-
|
|
972
|
-
const favicon = this.getFaviconElement();
|
|
973
|
-
favicon.href = urlWithCacheBuster;
|
|
974
|
-
},
|
|
907
|
+
// Collecter les URLs depuis tous les éléments
|
|
908
|
+
let faviconUrl = null;
|
|
909
|
+
let darkUrl = null;
|
|
975
910
|
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
const updateFavicon = function(e) {
|
|
980
|
-
const darkModeOn = e ? e.matches : window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
981
|
-
const selectedUrl = darkModeOn ? darkUrl : lightUrl;
|
|
982
|
-
bbContents.modules.favicon.setFavicon(selectedUrl);
|
|
983
|
-
};
|
|
984
|
-
|
|
985
|
-
// Initialiser le favicon au chargement de la page
|
|
986
|
-
updateFavicon();
|
|
911
|
+
elements.forEach(function(element) {
|
|
912
|
+
const light = bbContents._getAttr(element, 'bb-favicon') || bbContents._getAttr(element, 'favicon');
|
|
913
|
+
const dark = bbContents._getAttr(element, 'bb-favicon-dark') || bbContents._getAttr(element, 'favicon-dark');
|
|
987
914
|
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
915
|
+
if (light) faviconUrl = light;
|
|
916
|
+
if (dark) darkUrl = dark;
|
|
917
|
+
});
|
|
918
|
+
|
|
919
|
+
// Appliquer la logique
|
|
920
|
+
if (faviconUrl && darkUrl) {
|
|
921
|
+
this.setupDarkMode(faviconUrl, darkUrl);
|
|
922
|
+
} else if (faviconUrl) {
|
|
923
|
+
this.setFavicon(faviconUrl);
|
|
924
|
+
bbContents.utils.log('Favicon changé:', faviconUrl);
|
|
995
925
|
}
|
|
996
926
|
},
|
|
927
|
+
|
|
928
|
+
// Helper: Récupérer ou créer un élément favicon
|
|
929
|
+
getFaviconElement: function() {
|
|
930
|
+
let favicon = document.querySelector('link[rel="icon"]') ||
|
|
931
|
+
document.querySelector('link[rel="shortcut icon"]');
|
|
932
|
+
if (!favicon) {
|
|
933
|
+
favicon = document.createElement('link');
|
|
934
|
+
favicon.rel = 'icon';
|
|
935
|
+
document.head.appendChild(favicon);
|
|
936
|
+
}
|
|
937
|
+
return favicon;
|
|
938
|
+
},
|
|
939
|
+
|
|
940
|
+
// Changer le favicon
|
|
941
|
+
setFavicon: function(url) {
|
|
942
|
+
if (!url) return;
|
|
943
|
+
|
|
944
|
+
// Ajouter un timestamp pour forcer le rafraîchissement du cache
|
|
945
|
+
const cacheBuster = '?v=' + Date.now();
|
|
946
|
+
const urlWithCacheBuster = url + cacheBuster;
|
|
947
|
+
|
|
948
|
+
const favicon = this.getFaviconElement();
|
|
949
|
+
favicon.href = urlWithCacheBuster;
|
|
950
|
+
},
|
|
951
|
+
|
|
952
|
+
// Support dark mode (méthode simplifiée et directe)
|
|
953
|
+
setupDarkMode: function(lightUrl, darkUrl) {
|
|
954
|
+
// Fonction pour mettre à jour le favicon selon le mode sombre
|
|
955
|
+
const updateFavicon = function(e) {
|
|
956
|
+
const darkModeOn = e ? e.matches : window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
957
|
+
const selectedUrl = darkModeOn ? darkUrl : lightUrl;
|
|
958
|
+
bbContents.modules.favicon.setFavicon(selectedUrl);
|
|
959
|
+
};
|
|
960
|
+
|
|
961
|
+
// Initialiser le favicon au chargement de la page
|
|
962
|
+
updateFavicon();
|
|
963
|
+
|
|
964
|
+
// Écouter les changements du mode sombre
|
|
965
|
+
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
966
|
+
if (typeof darkModeMediaQuery.addEventListener === 'function') {
|
|
967
|
+
darkModeMediaQuery.addEventListener('change', updateFavicon);
|
|
968
|
+
} else if (typeof darkModeMediaQuery.addListener === 'function') {
|
|
969
|
+
darkModeMediaQuery.addListener(updateFavicon);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
},
|
|
997
973
|
|
|
998
974
|
// Module YouTube Feed
|
|
999
975
|
youtube: {
|
|
@@ -1046,7 +1022,7 @@
|
|
|
1046
1022
|
}
|
|
1047
1023
|
},
|
|
1048
1024
|
|
|
1049
|
-
|
|
1025
|
+
detect: function(scope) {
|
|
1050
1026
|
return scope.querySelector('[bb-youtube-channel]') !== null;
|
|
1051
1027
|
},
|
|
1052
1028
|
|
|
@@ -1115,7 +1091,7 @@
|
|
|
1115
1091
|
} else {
|
|
1116
1092
|
// Timeout après 5 secondes
|
|
1117
1093
|
element.innerHTML = '<div style="padding: 20px; background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px; color: #dc2626;"><strong>Configuration YouTube manquante</strong><br>Ajoutez dans le <head> :<br><code style="display: block; background: #f3f4f6; padding: 10px; margin: 10px 0; border-radius: 4px; font-family: monospace;"><script><br>bbContents.config.youtubeEndpoint = \'votre-worker-url\';<br></script></code></div>';
|
|
1118
|
-
|
|
1094
|
+
return;
|
|
1119
1095
|
}
|
|
1120
1096
|
}
|
|
1121
1097
|
|
|
@@ -1134,9 +1110,9 @@
|
|
|
1134
1110
|
|
|
1135
1111
|
if (!template) {
|
|
1136
1112
|
element.innerHTML = '<div style="padding: 20px; background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px; color: #dc2626;"><strong>Template manquant</strong><br>Ajoutez un élément avec l\'attribut bb-youtube-item</div>';
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1140
1116
|
// Cacher le template original
|
|
1141
1117
|
template.style.display = 'none';
|
|
1142
1118
|
|
|
@@ -1163,7 +1139,7 @@
|
|
|
1163
1139
|
const newCachedData = this.cache.get(cacheKey);
|
|
1164
1140
|
if (newCachedData && newCachedData.value) {
|
|
1165
1141
|
this.generateYouTubeFeed(container, template, newCachedData.value, allowShorts, language);
|
|
1166
|
-
|
|
1142
|
+
} else {
|
|
1167
1143
|
container.innerHTML = '<div style="padding: 20px; text-align: center; color: #6b7280;">Erreur de chargement</div>';
|
|
1168
1144
|
}
|
|
1169
1145
|
} else {
|
|
@@ -1203,7 +1179,6 @@
|
|
|
1203
1179
|
window[loadingKey] = false;
|
|
1204
1180
|
})
|
|
1205
1181
|
.catch(error => {
|
|
1206
|
-
console.error('Erreur API YouTube:', error);
|
|
1207
1182
|
// Erreur dans le module youtube
|
|
1208
1183
|
|
|
1209
1184
|
// Libérer le verrou en cas d'erreur
|
|
@@ -1309,7 +1284,7 @@
|
|
|
1309
1284
|
if (bbContents.config.debug) {
|
|
1310
1285
|
// Thumbnail optimisée
|
|
1311
1286
|
}
|
|
1312
|
-
|
|
1287
|
+
} else {
|
|
1313
1288
|
// Aucune thumbnail disponible
|
|
1314
1289
|
}
|
|
1315
1290
|
}
|