@bebranded/bb-contents 1.0.147 → 1.0.149

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.
Files changed (2) hide show
  1. package/bb-contents.js +135 -53
  2. 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.147
4
+ * @version 1.0.148
5
5
  * @author BeBranded
6
6
  * @license MIT
7
7
  * @website https://www.bebranded.xyz
@@ -32,11 +32,11 @@
32
32
  window._bbContentsInitialized = true;
33
33
 
34
34
  // Log de démarrage simple (une seule fois)
35
- console.log('bb-contents | v1.0.147');
35
+ console.log('bb-contents | v1.0.149');
36
36
 
37
37
  // Configuration
38
38
  const config = {
39
- version: '1.0.147',
39
+ version: '1.0.148',
40
40
  debug: false, // Debug désactivé pour rendu propre
41
41
  prefix: 'bb-', // utilisé pour générer les sélecteurs (data-bb-*)
42
42
  youtubeEndpoint: null, // URL du worker YouTube (à définir par l'utilisateur)
@@ -508,61 +508,135 @@
508
508
  forceImagesDisplay(repeatBlock1);
509
509
  forceImagesDisplay(repeatBlock2);
510
510
 
511
- // Pour les marquees horizontaux, utiliser position relative (plus simple et plus fiable)
512
- if (!isVertical) {
513
- scrollContainer.appendChild(mainBlock);
514
- scrollContainer.appendChild(repeatBlock1);
515
- scrollContainer.appendChild(repeatBlock2);
516
- mainContainer.appendChild(scrollContainer);
517
-
518
- // Calculer la hauteur maximale des items après ajout au DOM
519
- requestAnimationFrame(() => {
520
- requestAnimationFrame(() => {
521
- const items = mainBlock.querySelectorAll('.bb-marquee_item, [role="listitem"], > *');
522
- let maxHeight = 0;
523
- items.forEach(function(item) {
524
- const itemHeight = item.offsetHeight;
525
- if (itemHeight > maxHeight) {
526
- maxHeight = itemHeight;
511
+ // NOUVELLE APPROCHE: Ajouter temporairement les copies au DOM (hors écran)
512
+ // pour forcer le navigateur à les rendre complètement avant l'animation
513
+ const tempContainer = document.createElement('div');
514
+ tempContainer.style.cssText = 'position: absolute; left: -9999px; top: -9999px; visibility: hidden;';
515
+ tempContainer.appendChild(repeatBlock1);
516
+ tempContainer.appendChild(repeatBlock2);
517
+ document.body.appendChild(tempContainer);
518
+
519
+ // Forcer le rendu en vérifiant que toutes les images sont vraiment chargées et rendues
520
+ const waitForImagesRender = function(block) {
521
+ return new Promise(function(resolve) {
522
+ const images = block.querySelectorAll('img');
523
+ if (images.length === 0) {
524
+ resolve();
525
+ return;
526
+ }
527
+
528
+ let renderedCount = 0;
529
+ const totalImages = images.length;
530
+
531
+ const checkRendered = function() {
532
+ if (renderedCount >= totalImages) {
533
+ resolve();
534
+ }
535
+ };
536
+
537
+ images.forEach(function(img) {
538
+ // Vérifier que l'image est vraiment rendue (naturalWidth > 0 ET dans le DOM)
539
+ const checkImage = function() {
540
+ if (img.complete && img.naturalWidth > 0 && img.naturalHeight > 0 && img.offsetWidth > 0) {
541
+ renderedCount++;
542
+ checkRendered();
543
+ } else {
544
+ // Réessayer après un court délai
545
+ setTimeout(checkImage, 10);
527
546
  }
528
- });
547
+ };
529
548
 
530
- // Si aucun item trouvé, essayer de prendre la hauteur du scrollContainer
531
- if (maxHeight === 0) {
532
- maxHeight = scrollContainer.offsetHeight;
549
+ // Forcer le chargement si nécessaire
550
+ if (img.dataset.src && !img.src) {
551
+ img.src = img.dataset.src;
533
552
  }
534
553
 
535
- // Appliquer la hauteur calculée au mainContainer si elle est valide
536
- if (maxHeight > 0) {
537
- mainContainer.style.height = maxHeight + 'px';
554
+ if (img.complete && img.naturalWidth > 0 && img.offsetWidth > 0) {
555
+ renderedCount++;
556
+ checkRendered();
557
+ } else {
558
+ img.onload = function() {
559
+ setTimeout(checkImage, 10);
560
+ };
561
+ checkImage();
538
562
  }
539
563
  });
564
+
565
+ // Timeout de sécurité
566
+ setTimeout(function() {
567
+ if (renderedCount < totalImages) {
568
+ renderedCount = totalImages;
569
+ checkRendered();
570
+ }
571
+ }, 2000);
540
572
  });
541
- } else {
542
- // Pour vertical, garder le comportement actuel
543
- scrollContainer.appendChild(mainBlock);
544
- scrollContainer.appendChild(repeatBlock1);
545
- scrollContainer.appendChild(repeatBlock2);
546
- mainContainer.appendChild(scrollContainer);
547
- }
573
+ };
548
574
 
549
- element.innerHTML = '';
550
- element.appendChild(mainContainer);
551
- element.setAttribute('data-bb-marquee-processed', 'true');
575
+ // Attendre que toutes les images soient rendues dans les copies
576
+ Promise.all([
577
+ waitForImagesRender(repeatBlock1),
578
+ waitForImagesRender(repeatBlock2)
579
+ ]).then(function() {
580
+ // Retirer les copies du conteneur temporaire
581
+ document.body.removeChild(tempContainer);
582
+
583
+ // Maintenant ajouter les copies au scrollContainer
584
+ // Les images sont maintenant complètement rendues
585
+ if (!isVertical) {
586
+ scrollContainer.appendChild(mainBlock);
587
+ scrollContainer.appendChild(repeatBlock1);
588
+ scrollContainer.appendChild(repeatBlock2);
589
+ mainContainer.appendChild(scrollContainer);
590
+
591
+ // Calculer la hauteur maximale des items après ajout au DOM
592
+ requestAnimationFrame(() => {
593
+ requestAnimationFrame(() => {
594
+ const items = mainBlock.querySelectorAll('.bb-marquee_item, [role="listitem"], > *');
595
+ let maxHeight = 0;
596
+ items.forEach(function(item) {
597
+ const itemHeight = item.offsetHeight;
598
+ if (itemHeight > maxHeight) {
599
+ maxHeight = itemHeight;
600
+ }
601
+ });
602
+
603
+ // Si aucun item trouvé, essayer de prendre la hauteur du scrollContainer
604
+ if (maxHeight === 0) {
605
+ maxHeight = scrollContainer.offsetHeight;
606
+ }
607
+
608
+ // Appliquer la hauteur calculée au mainContainer si elle est valide
609
+ if (maxHeight > 0) {
610
+ mainContainer.style.height = maxHeight + 'px';
611
+ }
612
+ });
613
+ });
614
+ } else {
615
+ // Pour vertical, garder le comportement actuel
616
+ scrollContainer.appendChild(mainBlock);
617
+ scrollContainer.appendChild(repeatBlock1);
618
+ scrollContainer.appendChild(repeatBlock2);
619
+ mainContainer.appendChild(scrollContainer);
620
+ }
621
+
622
+ element.innerHTML = '';
623
+ element.appendChild(mainContainer);
624
+ element.setAttribute('data-bb-marquee-processed', 'true');
552
625
 
553
- // Attendre un peu pour s'assurer que le rendu est complet
554
- // Les images sont déjà chargées donc pas besoin d'attendre leur chargement
555
- requestAnimationFrame(() => {
626
+ // Attendre un peu pour s'assurer que le rendu est complet
627
+ // Les images sont maintenant complètement rendues
556
628
  requestAnimationFrame(() => {
557
- // Maintenant démarrer l'animation
558
- const initDelay = isVertical ? 500 : 100;
559
- setTimeout(() => {
560
- this.initAnimation(element, scrollContainer, mainBlock, {
561
- speed, direction, pauseOnHover, gap, isVertical, useAutoHeight
562
- });
563
- }, initDelay);
629
+ requestAnimationFrame(() => {
630
+ // Maintenant démarrer l'animation
631
+ const initDelay = isVertical ? 500 : 100;
632
+ setTimeout(() => {
633
+ this.initAnimation(element, scrollContainer, mainBlock, {
634
+ speed, direction, pauseOnHover, gap, isVertical, useAutoHeight
635
+ });
636
+ }, initDelay);
637
+ });
564
638
  });
565
- });
639
+ }.bind(this));
566
640
  }.bind(this)).catch(function() {
567
641
  // En cas d'erreur, créer les copies quand même et démarrer
568
642
  const repeatBlock1 = mainBlock.cloneNode(true);
@@ -941,10 +1015,14 @@
941
1015
 
942
1016
  if (direction === (isVertical ? 'bottom' : 'right')) {
943
1017
  currentPosition += step * deltaTime;
944
- if (currentPosition >= 0) {
945
- currentPosition = -(finalContentSize + gapSize);
1018
+ // Reset BEAUCOUP PLUS TÔT pour "right" aussi (comme pour "left") - Safari
1019
+ // Reset à 80% du chemin au lieu d'attendre 100% pour avoir une marge de sécurité
1020
+ const resetThreshold = -(0.2 * (finalContentSize + gapSize)); // 80% du chemin (on est à -20%)
1021
+ if (currentPosition >= resetThreshold) {
1022
+ // Reset en gardant la position relative pour éviter le saut visible
1023
+ currentPosition = currentPosition - (finalContentSize + gapSize);
946
1024
  }
947
- } else {
1025
+ } else {
948
1026
  currentPosition -= step * deltaTime;
949
1027
  // Reset BEAUCOUP PLUS TÔT pour éviter toute saccade visible (Safari)
950
1028
  // Reset à 80% du chemin au lieu d'attendre 100% pour avoir une marge de sécurité
@@ -1028,9 +1106,13 @@
1028
1106
 
1029
1107
  if (direction === (isVertical ? 'bottom' : 'right')) {
1030
1108
  currentPosition += step * clampedDelta;
1031
- // Reset AVANT que le bloc ne sorte complètement pour éviter la saccade
1032
- if (currentPosition >= 0) {
1033
- currentPosition = -(contentSize + gapSize);
1109
+ // Reset BEAUCOUP PLUS TÔT pour "right" aussi (comme pour "left")
1110
+ // Reset à 80% du chemin au lieu d'attendre 100% pour avoir une marge de sécurité
1111
+ // Cela garantit que la copie suivante est toujours visible avant le reset
1112
+ const resetThreshold = -(0.2 * (contentSize + gapSize)); // 80% du chemin (on est à -20%)
1113
+ if (currentPosition >= resetThreshold) {
1114
+ // Reset en gardant la position relative pour éviter le saut visible
1115
+ currentPosition = currentPosition - (contentSize + gapSize);
1034
1116
  }
1035
1117
  } else {
1036
1118
  currentPosition -= step * clampedDelta;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bebranded/bb-contents",
3
- "version": "1.0.147",
3
+ "version": "1.0.149",
4
4
  "description": "Contenus additionnels français pour Webflow",
5
5
  "main": "bb-contents.js",
6
6
  "scripts": {