@bebranded/bb-contents 1.0.146 → 1.0.148
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 +181 -128
- 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.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.
|
|
35
|
+
console.log('bb-contents | v1.0.148');
|
|
36
36
|
|
|
37
37
|
// Configuration
|
|
38
38
|
const config = {
|
|
39
|
-
version: '1.0.
|
|
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)
|
|
@@ -347,57 +347,9 @@
|
|
|
347
347
|
const mainBlock = document.createElement('div');
|
|
348
348
|
mainBlock.innerHTML = originalHTML;
|
|
349
349
|
|
|
350
|
-
//
|
|
351
|
-
//
|
|
352
|
-
|
|
353
|
-
if (!isVertical) {
|
|
354
|
-
setTimeout(() => {
|
|
355
|
-
const marqueeItems = mainBlock.querySelectorAll('.bb-marquee_item, [role="listitem"]');
|
|
356
|
-
marqueeItems.forEach(item => {
|
|
357
|
-
// Préserver la largeur de l'item définie dans Webflow
|
|
358
|
-
const computedStyle = getComputedStyle(item);
|
|
359
|
-
const itemWidth = computedStyle.width;
|
|
360
|
-
if (itemWidth && itemWidth !== 'auto' && itemWidth !== '0px') {
|
|
361
|
-
item.style.minWidth = itemWidth;
|
|
362
|
-
item.style.width = itemWidth;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// Permettre le retour à la ligne pour les conteneurs de texte
|
|
366
|
-
const textContainers = item.querySelectorAll('.use-case_client, .testimonial_client-info, [class*="text"], p, span');
|
|
367
|
-
textContainers.forEach(container => {
|
|
368
|
-
const containerComputed = getComputedStyle(container);
|
|
369
|
-
// Si l'élément a une largeur définie, la préserver
|
|
370
|
-
if (containerComputed.width && containerComputed.width !== 'auto' && containerComputed.width !== '0px') {
|
|
371
|
-
container.style.width = containerComputed.width;
|
|
372
|
-
} else {
|
|
373
|
-
// Sinon, prendre 100% de la largeur du parent
|
|
374
|
-
container.style.width = '100%';
|
|
375
|
-
}
|
|
376
|
-
// Forcer le retour à la ligne
|
|
377
|
-
container.style.whiteSpace = 'normal';
|
|
378
|
-
container.style.wordWrap = 'break-word';
|
|
379
|
-
container.style.overflowWrap = 'break-word';
|
|
380
|
-
});
|
|
381
|
-
});
|
|
382
|
-
}, 0);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
mainBlock.style.cssText = `
|
|
386
|
-
display: flex;
|
|
387
|
-
${isVertical ? 'flex-direction: column;' : ''}
|
|
388
|
-
align-items: center;
|
|
389
|
-
gap: ${gap}px;
|
|
390
|
-
${isVertical ? '' : 'white-space: nowrap;'}
|
|
391
|
-
flex-shrink: 0;
|
|
392
|
-
${isVertical ? 'min-height: 100px;' : ''}
|
|
393
|
-
`;
|
|
394
|
-
|
|
395
|
-
// Créer 3 copies pour le défilement infini
|
|
396
|
-
const repeatBlock1 = mainBlock.cloneNode(true);
|
|
397
|
-
const repeatBlock2 = mainBlock.cloneNode(true);
|
|
398
|
-
|
|
399
|
-
// Forcer le chargement COMPLET des images dans les copies pour éviter l'apparition tardive
|
|
400
|
-
const preloadImagesInBlock = function(block) {
|
|
350
|
+
// IMPORTANT: Forcer le chargement de TOUTES les images dans mainBlock AVANT de cloner
|
|
351
|
+
// Cela garantit que les images sont dans le cache du navigateur avant le clonage
|
|
352
|
+
const preloadAllImagesFirst = function(block) {
|
|
401
353
|
return new Promise(function(resolve) {
|
|
402
354
|
const images = block.querySelectorAll('img');
|
|
403
355
|
if (images.length === 0) {
|
|
@@ -421,7 +373,7 @@
|
|
|
421
373
|
img.src = img.dataset.src;
|
|
422
374
|
}
|
|
423
375
|
|
|
424
|
-
// Si l'image est déjà
|
|
376
|
+
// Si l'image est déjà complètement chargée
|
|
425
377
|
if (img.complete && img.naturalWidth > 0 && img.naturalHeight > 0) {
|
|
426
378
|
loadedCount++;
|
|
427
379
|
checkComplete();
|
|
@@ -429,12 +381,20 @@
|
|
|
429
381
|
// Précharger avec new Image() pour forcer le cache
|
|
430
382
|
const preloadImg = new Image();
|
|
431
383
|
preloadImg.onload = function() {
|
|
432
|
-
//
|
|
433
|
-
if (img.src
|
|
434
|
-
img.src = img.src;
|
|
384
|
+
// Forcer aussi le chargement dans l'image du DOM
|
|
385
|
+
if (img.src) {
|
|
386
|
+
img.src = img.src;
|
|
435
387
|
}
|
|
436
|
-
|
|
437
|
-
|
|
388
|
+
// Attendre que l'image du DOM soit aussi chargée
|
|
389
|
+
const checkDomImage = function() {
|
|
390
|
+
if (img.complete && img.naturalWidth > 0 && img.naturalHeight > 0) {
|
|
391
|
+
loadedCount++;
|
|
392
|
+
checkComplete();
|
|
393
|
+
} else {
|
|
394
|
+
setTimeout(checkDomImage, 10);
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
setTimeout(checkDomImage, 10);
|
|
438
398
|
};
|
|
439
399
|
preloadImg.onerror = function() {
|
|
440
400
|
errorCount++;
|
|
@@ -451,81 +411,147 @@
|
|
|
451
411
|
}
|
|
452
412
|
|
|
453
413
|
// Écouter aussi le chargement de l'image dans le DOM
|
|
454
|
-
const originalOnload = img.onload;
|
|
455
414
|
img.onload = function() {
|
|
456
|
-
if (
|
|
457
|
-
if (!img.complete || img.naturalWidth === 0) {
|
|
458
|
-
// Attendre encore un peu
|
|
459
|
-
setTimeout(function() {
|
|
460
|
-
if (img.complete && img.naturalWidth > 0) {
|
|
461
|
-
loadedCount++;
|
|
462
|
-
checkComplete();
|
|
463
|
-
}
|
|
464
|
-
}, 50);
|
|
465
|
-
} else {
|
|
415
|
+
if (img.complete && img.naturalWidth > 0 && img.naturalHeight > 0) {
|
|
466
416
|
loadedCount++;
|
|
467
417
|
checkComplete();
|
|
468
418
|
}
|
|
469
419
|
};
|
|
470
420
|
|
|
471
|
-
//
|
|
421
|
+
// Forcer le chargement si l'image a déjà un src
|
|
472
422
|
if (img.src) {
|
|
473
423
|
img.src = img.src;
|
|
474
424
|
}
|
|
475
425
|
}
|
|
476
426
|
});
|
|
427
|
+
|
|
428
|
+
// Timeout de sécurité (max 5 secondes)
|
|
429
|
+
setTimeout(function() {
|
|
430
|
+
if (loadedCount + errorCount < totalImages) {
|
|
431
|
+
errorCount = totalImages - loadedCount;
|
|
432
|
+
checkComplete();
|
|
433
|
+
}
|
|
434
|
+
}, 5000);
|
|
477
435
|
});
|
|
478
436
|
};
|
|
479
437
|
|
|
480
|
-
//
|
|
438
|
+
// Permettre le retour à la ligne pour le texte dans les items du marquee
|
|
439
|
+
// Le white-space: nowrap sur le conteneur flex empêche les items de se retourner,
|
|
440
|
+
// mais ne doit pas empêcher le texte à l'intérieur des items de faire plusieurs lignes
|
|
481
441
|
if (!isVertical) {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
let maxHeight = 0;
|
|
492
|
-
items.forEach(function(item) {
|
|
493
|
-
const itemHeight = item.offsetHeight;
|
|
494
|
-
if (itemHeight > maxHeight) {
|
|
495
|
-
maxHeight = itemHeight;
|
|
496
|
-
}
|
|
497
|
-
});
|
|
498
|
-
|
|
499
|
-
// Si aucun item trouvé, essayer de prendre la hauteur du scrollContainer
|
|
500
|
-
if (maxHeight === 0) {
|
|
501
|
-
maxHeight = scrollContainer.offsetHeight;
|
|
442
|
+
setTimeout(() => {
|
|
443
|
+
const marqueeItems = mainBlock.querySelectorAll('.bb-marquee_item, [role="listitem"]');
|
|
444
|
+
marqueeItems.forEach(item => {
|
|
445
|
+
// Préserver la largeur de l'item définie dans Webflow
|
|
446
|
+
const computedStyle = getComputedStyle(item);
|
|
447
|
+
const itemWidth = computedStyle.width;
|
|
448
|
+
if (itemWidth && itemWidth !== 'auto' && itemWidth !== '0px') {
|
|
449
|
+
item.style.minWidth = itemWidth;
|
|
450
|
+
item.style.width = itemWidth;
|
|
502
451
|
}
|
|
503
452
|
|
|
504
|
-
//
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
453
|
+
// Permettre le retour à la ligne pour les conteneurs de texte
|
|
454
|
+
const textContainers = item.querySelectorAll('.use-case_client, .testimonial_client-info, [class*="text"], p, span');
|
|
455
|
+
textContainers.forEach(container => {
|
|
456
|
+
const containerComputed = getComputedStyle(container);
|
|
457
|
+
// Si l'élément a une largeur définie, la préserver
|
|
458
|
+
if (containerComputed.width && containerComputed.width !== 'auto' && containerComputed.width !== '0px') {
|
|
459
|
+
container.style.width = containerComputed.width;
|
|
460
|
+
} else {
|
|
461
|
+
// Sinon, prendre 100% de la largeur du parent
|
|
462
|
+
container.style.width = '100%';
|
|
463
|
+
}
|
|
464
|
+
// Forcer le retour à la ligne
|
|
465
|
+
container.style.whiteSpace = 'normal';
|
|
466
|
+
container.style.wordWrap = 'break-word';
|
|
467
|
+
container.style.overflowWrap = 'break-word';
|
|
468
|
+
});
|
|
508
469
|
});
|
|
509
|
-
});
|
|
510
|
-
} else {
|
|
511
|
-
// Pour vertical, garder le comportement actuel
|
|
512
|
-
scrollContainer.appendChild(mainBlock);
|
|
513
|
-
scrollContainer.appendChild(repeatBlock1);
|
|
514
|
-
scrollContainer.appendChild(repeatBlock2);
|
|
515
|
-
mainContainer.appendChild(scrollContainer);
|
|
470
|
+
}, 0);
|
|
516
471
|
}
|
|
517
472
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
473
|
+
mainBlock.style.cssText = `
|
|
474
|
+
display: flex;
|
|
475
|
+
${isVertical ? 'flex-direction: column;' : ''}
|
|
476
|
+
align-items: center;
|
|
477
|
+
gap: ${gap}px;
|
|
478
|
+
${isVertical ? '' : 'white-space: nowrap;'}
|
|
479
|
+
flex-shrink: 0;
|
|
480
|
+
${isVertical ? 'min-height: 100px;' : ''}
|
|
481
|
+
`;
|
|
482
|
+
|
|
483
|
+
// NOUVELLE APPROCHE: Attendre que TOUTES les images du mainBlock soient chargées AVANT de cloner
|
|
484
|
+
// Cela garantit que les copies héritent d'images déjà dans le cache du navigateur
|
|
485
|
+
preloadAllImagesFirst(mainBlock).then(function() {
|
|
486
|
+
// Maintenant créer les copies - les images sont déjà en cache
|
|
487
|
+
const repeatBlock1 = mainBlock.cloneNode(true);
|
|
488
|
+
const repeatBlock2 = mainBlock.cloneNode(true);
|
|
489
|
+
|
|
490
|
+
// Forcer l'affichage immédiat des images dans les copies (elles sont en cache)
|
|
491
|
+
const forceImagesDisplay = function(block) {
|
|
492
|
+
const images = block.querySelectorAll('img');
|
|
493
|
+
images.forEach(function(img) {
|
|
494
|
+
if (img.dataset.src && !img.src) {
|
|
495
|
+
img.src = img.dataset.src;
|
|
496
|
+
}
|
|
497
|
+
// Forcer le chargement et l'affichage
|
|
498
|
+
if (img.src) {
|
|
499
|
+
img.src = img.src;
|
|
500
|
+
img.style.opacity = '1';
|
|
501
|
+
img.style.visibility = 'visible';
|
|
502
|
+
// Forcer un reflow pour s'assurer que l'image est rendue
|
|
503
|
+
void img.offsetHeight;
|
|
504
|
+
}
|
|
505
|
+
});
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
forceImagesDisplay(repeatBlock1);
|
|
509
|
+
forceImagesDisplay(repeatBlock2);
|
|
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;
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
// Si aucun item trouvé, essayer de prendre la hauteur du scrollContainer
|
|
531
|
+
if (maxHeight === 0) {
|
|
532
|
+
maxHeight = scrollContainer.offsetHeight;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Appliquer la hauteur calculée au mainContainer si elle est valide
|
|
536
|
+
if (maxHeight > 0) {
|
|
537
|
+
mainContainer.style.height = maxHeight + 'px';
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
});
|
|
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
|
+
}
|
|
548
|
+
|
|
549
|
+
element.innerHTML = '';
|
|
550
|
+
element.appendChild(mainContainer);
|
|
551
|
+
element.setAttribute('data-bb-marquee-processed', 'true');
|
|
552
|
+
|
|
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
|
|
529
555
|
requestAnimationFrame(() => {
|
|
530
556
|
requestAnimationFrame(() => {
|
|
531
557
|
// Maintenant démarrer l'animation
|
|
@@ -538,13 +564,32 @@
|
|
|
538
564
|
});
|
|
539
565
|
});
|
|
540
566
|
}.bind(this)).catch(function() {
|
|
541
|
-
// En cas d'erreur,
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
567
|
+
// En cas d'erreur, créer les copies quand même et démarrer
|
|
568
|
+
const repeatBlock1 = mainBlock.cloneNode(true);
|
|
569
|
+
const repeatBlock2 = mainBlock.cloneNode(true);
|
|
570
|
+
|
|
571
|
+
if (!isVertical) {
|
|
572
|
+
scrollContainer.appendChild(mainBlock);
|
|
573
|
+
scrollContainer.appendChild(repeatBlock1);
|
|
574
|
+
scrollContainer.appendChild(repeatBlock2);
|
|
575
|
+
mainContainer.appendChild(scrollContainer);
|
|
576
|
+
} else {
|
|
577
|
+
scrollContainer.appendChild(mainBlock);
|
|
578
|
+
scrollContainer.appendChild(repeatBlock1);
|
|
579
|
+
scrollContainer.appendChild(repeatBlock2);
|
|
580
|
+
mainContainer.appendChild(scrollContainer);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
element.innerHTML = '';
|
|
584
|
+
element.appendChild(mainContainer);
|
|
585
|
+
element.setAttribute('data-bb-marquee-processed', 'true');
|
|
586
|
+
|
|
587
|
+
const initDelay = isVertical ? 500 : 300;
|
|
588
|
+
setTimeout(() => {
|
|
589
|
+
this.initAnimation(element, scrollContainer, mainBlock, {
|
|
590
|
+
speed, direction, pauseOnHover, gap, isVertical, useAutoHeight
|
|
591
|
+
});
|
|
592
|
+
}, initDelay);
|
|
548
593
|
}.bind(this));
|
|
549
594
|
});
|
|
550
595
|
},
|
|
@@ -896,10 +941,14 @@
|
|
|
896
941
|
|
|
897
942
|
if (direction === (isVertical ? 'bottom' : 'right')) {
|
|
898
943
|
currentPosition += step * deltaTime;
|
|
899
|
-
|
|
900
|
-
|
|
944
|
+
// Reset BEAUCOUP PLUS TÔT pour "right" aussi (comme pour "left") - Safari
|
|
945
|
+
// Reset à 80% du chemin au lieu d'attendre 100% pour avoir une marge de sécurité
|
|
946
|
+
const resetThreshold = -(0.2 * (finalContentSize + gapSize)); // 80% du chemin (on est à -20%)
|
|
947
|
+
if (currentPosition >= resetThreshold) {
|
|
948
|
+
// Reset en gardant la position relative pour éviter le saut visible
|
|
949
|
+
currentPosition = currentPosition - (finalContentSize + gapSize);
|
|
901
950
|
}
|
|
902
|
-
|
|
951
|
+
} else {
|
|
903
952
|
currentPosition -= step * deltaTime;
|
|
904
953
|
// Reset BEAUCOUP PLUS TÔT pour éviter toute saccade visible (Safari)
|
|
905
954
|
// Reset à 80% du chemin au lieu d'attendre 100% pour avoir une marge de sécurité
|
|
@@ -983,9 +1032,13 @@
|
|
|
983
1032
|
|
|
984
1033
|
if (direction === (isVertical ? 'bottom' : 'right')) {
|
|
985
1034
|
currentPosition += step * clampedDelta;
|
|
986
|
-
// Reset
|
|
987
|
-
|
|
988
|
-
|
|
1035
|
+
// Reset BEAUCOUP PLUS TÔT pour "right" aussi (comme pour "left")
|
|
1036
|
+
// Reset à 80% du chemin au lieu d'attendre 100% pour avoir une marge de sécurité
|
|
1037
|
+
// Cela garantit que la copie suivante est toujours visible avant le reset
|
|
1038
|
+
const resetThreshold = -(0.2 * (contentSize + gapSize)); // 80% du chemin (on est à -20%)
|
|
1039
|
+
if (currentPosition >= resetThreshold) {
|
|
1040
|
+
// Reset en gardant la position relative pour éviter le saut visible
|
|
1041
|
+
currentPosition = currentPosition - (contentSize + gapSize);
|
|
989
1042
|
}
|
|
990
1043
|
} else {
|
|
991
1044
|
currentPosition -= step * clampedDelta;
|