1/*! 2 * VV Instagram Feed - filter & interactions 3 * v1.0.8 4 * 5 * Catégorise les publications SociableKit par hashtag, filtre/arrange 6 * via Isotope, gère la préview vidéo au survol (desktop) et au tap 7 * (mobile), et ouvre la publication Instagram au clic. 8 * 9 * Correctif v1.0.3 : le clic sur une publication ne faisait plus rien 10 * (ni sur ordinateur, ni au second tap sur mobile) car le gestionnaire 11 * de clic interceptait TOUS les clics (stopPropagation) mais ne 12 * déclenchait une action que sur appareil tactile. Sur ordinateur, 13 * aucune ouverture n'était donc jamais effectuée. Le correctif utilise 14 * l'attribut data-link (fourni par SociableKit sur chaque publication, 15 * et vérifié présent et correct) pour ouvrir la publication Instagram 16 * dans un nouvel onglet, dans tous les cas : 17 * - Ordinateur / souris : clic = ouvre direct (le survol affiche déjà 18 * l'aperçu vidéo, donc pas besoin d'un "premier clic pour prévisualiser"). 19 * - Tactile : 1er tap = lance l'aperçu vidéo (comportement existant, 20 * inchangé) ; 2e tap sur la même publication = ouvre la publication. 21 * 22 * Correctif v1.0.4 : masque explicitement la légende d'origine de la 23 * publication (SociableKit peut l'afficher selon les réglages de leur 24 * tableau de bord, ou de façon incohérente selon le navigateur), pour 25 * garder un affichage propre quoi qu'il arrive côté SociableKit. 26 * 27 * Correctif v1.0.5 : certaines publications manquaient et des vidéos 28 * "clignotaient"/se chevauchaient, surtout remarqué sous Firefox. Piste 29 * retenue : SociableKit ajoute les publications par vagues, ce qui 30 * redéclenche le tri/réarrangement plusieurs fois ; sur une connexion 31 * plus lente, la fenêtre d'observation de 20s pouvait se couper avant 32 * la fin, et un réarrangement pendant la lecture d'un aperçu vidéo 33 * faisait bouger son emplacement en plein jeu. Fenêtre d'observation 34 * allongée (45s), regroupement des vagues plus large (300ms), et 35 * coupure propre de l'aperçu en cours avant tout réarrangement. 36 * N'a pas résolu le chevauchement des vidéos (confirmé par retour 37 * utilisateur sur Safari/Firefox après déploiement). 38 * 39 * Correctif v1.0.6 : l'aperçu vidéo superposait l'image et la vidéo 40 * via CSS Grid (grid-area:1/1 sur les deux, dans un conteneur 41 * height:auto). Sur une hauteur de ligne de grille "auto", la règle 42 * height:100% appliquée à la vidéo est une hauteur en pourcentage 43 * dont la base est indéfinie : Chrome la résout en pratique à la 44 * même hauteur que l'image, mais Firefox/Safari peuvent la résoudre 45 * autrement (ratio intrinsèque de la vidéo), ce qui rendait la vidéo 46 * plus grande/plus petite que l'image et donnait l'impression de deux 47 * visuels superposés/qui dépassent l'un de l'autre - cohérent avec le 48 * retour "ça marche mieux sous Chrome que Firefox/Safari". Remplacé 49 * par le motif standard et fiable sur tous les navigateurs : l'image 50 * reste en flux normal (c'est elle qui détermine la hauteur de la 51 * publication), et la vidéo est positionnée en position:absolute par- 52 * dessus avec inset:0 (haut/bas/gauche/droite à 0), ce qui la force à 53 * occuper exactement le même rectangle que l'image, sans dépendre 54 * d'un calcul de pourcentage ambigu. Ce correctif ne change rien au 55 * nombre de publications affichées (voir note plus bas). 56 * 57 * Correctif v1.0.7 : sur ordinateur, le clic ouvrait Instagram dans un 58 * nouvel onglet (comportement volontaire du correctif v1.0.3). Demande 59 * explicite : sur ordinateur, seul le survol doit agir (lecture de 60 * l'aperçu vidéo) â plus d'ouverture au clic. Le comportement tactile 61 * (1er tap = aperçu, 2e tap = ouverture) reste inchangé, il convenait 62 * déjà . 63 * 64 * Correctif v1.0.8 : sous Safari, le survol changeait bien la couleur 65 * (désaturation levée) mais la vidéo ne démarrait jamais, alors que 66 * Chrome/Firefox fonctionnaient normalement. Cause probable : avec 67 * preload="none", Safari n'entame pas toujours le chargement d'une 68 * vidéo après une affectation dynamique de src tant que load() n'est 69 * pas appelé explicitement (contrairement à Chrome/Firefox, plus 70 * tolérants ici). Ajout d'un appel explicite à load(), et renforcement 71 * de la mise en sourdine (attribut muted en plus de la propriété JS) 72 * pour éviter tout blocage de lecture automatique côté Safari. 73 */ 74(function(){'use strict';var CATEGORY_TAGS=window.VV_IF_CATEGORY_TAGS&&Object.keys(window.VV_IF_CATEGORY_TAGS).length?window.VV_IF_CATEGORY_TAGS:{studio:['vvstudio'],imprimerie:['vvimprimerie'],enseigne:['vvenseigne'],signaletique:['vvsignaletique'],textile:['vvtextile','vilainsvoisinstextile'],covering:['vvcovering'],foufou:['vvfoufou'],};var VV_TRANSITION_MS=400;var VV_GUTTER_PX=12;var VV_ROW_GAP_PX=VV_GUTTER_PX/2;var VV_BORDER_RADIUS_PX=8;var activeCategory=window.VV_FEED_CATEGORY||null;var itemSelector='.sk-instagram-feed-item';var captionSelector='.sk-ig-caption';var posterImgSelector='img.sk-ig-post-img';var maxWaitMs=45000;function getContainer(){return(document.querySelector('.sk-ig-all-posts')||document.querySelector('.sk-instagram-feed'))} 75function log(msg){if(window.VV_FEED_DEBUG){console.log('[vv-filter] '+msg)}} 76function extractTags(text){var found=[];var re=/#([a-z0-9_]+)/gi;var m;while((m=re.exec(text))!==null){found.push(m[1].toLowerCase())} 77return found} 78function injectStyles(){if(document.getElementById('vv-if-style'))return;var style=document.createElement('style');style.id='vv-if-style';style.textContent='.sk-instagram-feed-item{position:relative;height:auto!important;min-height:0!important;'+'width:23%!important;overflow:hidden!important;float:none!important;'+'padding:0!important;margin:0 0 '+VV_ROW_GAP_PX+'px 0!important;'+'border-radius:'+VV_BORDER_RADIUS_PX+'px!important;}'+'@media (max-width:700px){.sk-instagram-feed-item{width:31%!important;}}'+'@media (max-width:480px){.sk-instagram-feed-item{width:48%!important;}}'+'.sk-instagram-feed-item '+posterImgSelector+'{'+'position:relative;display:block!important;width:100%!important;height:auto!important;'+'z-index:1;filter:grayscale(100%);'+'transition:filter '+VV_TRANSITION_MS+'ms ease;}'+'.sk-instagram-feed-item.vv-hover-active '+posterImgSelector+'{filter:grayscale(0%);}'+'.vv-hover-video{position:absolute!important;top:0!important;left:0!important;'+'right:0!important;bottom:0!important;width:100%!important;height:100%!important;'+'object-fit:cover!important;display:block!important;'+'opacity:0;z-index:2;pointer-events:none!important;}'+'.sk-instagram-feed-item.vv-hover-active .vv-hover-video{opacity:1;}
78'+'.sk-instagram-feed-item .sk-ig-caption{display:none!important;}';document.head.appendChild(style)} 79function categorize(container){var items=container.querySelectorAll(itemSelector);var counts={};items.forEach(function(item){var captionEl=item.querySelector(captionSelector);var text=captionEl?captionEl.innerText||captionEl.textContent:item.innerText||'';var tags=extractTags(text);var matched=[];Object.keys(CATEGORY_TAGS).forEach(function(key){var aliases=CATEGORY_TAGS[key];var hit=aliases.some(function(tag){return tags.indexOf(tag)!==-1});if(hit){matched.push(key);item.classList.add('vv-cat-'+key);counts[key]=(counts[key]||0)+1}});item.setAttribute('data-vv-categories',matched.join(' '));if(!matched.length){item.classList.add('vv-cat-none')}});log('Publications catégorisées : '+items.length+' au total, répartition = '+JSON.stringify(counts));return items.length} 80function getPosterImg(item){return item.querySelector(posterImgSelector)} 81function ensureVideoEl(item){var vid=item.querySelector('.vv-hover-video');if(vid)return vid;var url=item.getAttribute('video-url');if(!url)return null;vid=document.createElement('video');vid.className='vv-hover-video';vid.muted=!0;vid.defaultMuted=!0;vid.setAttribute('muted','');vid.loop=!0;vid.playsInline=!0;vid.setAttribute('playsinline','');vid.setAttribute('webkit-playsinline','');vid.preload='none';item.appendChild(vid);return vid} 82function loadAndPlayVideo(vid,item){var isNewSrc=!vid.src;if(isNewSrc){var posterImg=getPosterImg(item);if(posterImg){vid.poster=posterImg.currentSrc||posterImg.src} 83vid.src=item.getAttribute('video-url');vid.load()} 84if(!isNewSrc){try{vid.currentTime=0}catch(e){}} 85var p=vid.play();if(p&&p.catch)p.catch(function(){})} 86function handleHoverStart(item){if(item.classList.contains('vv-hover-active'))return;var isVideo=item.getAttribute('data-type')==='video';var vid=isVideo?ensureVideoEl(item):null;item.classList.add('vv-hover-active');if(vid)loadAndPlayVideo(vid,item);} 87function handleHoverEnd(item){if(!item.classList.contains('vv-hover-active'))return;item.classList.remove('vv-hover-active');var vid=item.querySelector('.vv-hover-video');if(vid)vid.pause();} 88var VV_IS_TOUCH_DEVICE=!!(window.matchMedia&&window.matchMedia('(hover: none)').matches);var vvActiveTouchItem=null;function handleTouchTap(item){if(vvActiveTouchItem===item){handleHoverEnd(item);vvActiveTouchItem=null;return} 89if(vvActiveTouchItem){handleHoverEnd(vvActiveTouchItem)} 90handleHoverStart(item);vvActiveTouchItem=item} 91function openPost(item){var link=item.getAttribute('data-link');if(link)window.open(link,'_blank','noopener');} 92if(VV_IS_TOUCH_DEVICE){document.addEventListener('click',function(e){if(!vvActiveTouchItem)return;if(e.target.closest(itemSelector))return;handleHoverEnd(vvActiveTouchItem);vvActiveTouchItem=null})} 93function bindInteractions(container){if(container.dataset.vvBound)return;container.dataset.vvBound='1';container.addEventListener('mouseover',function(e){var item=e.target.closest(itemSelector);if(!item||!container.contains(item))return;if(item.contains(e.relatedTarget))return;handleHoverStart(item)});container.addEventListener('mouseout',function(e){var item=e.target.closest(itemSelector);if(!item||!container.contains(item))return;if(item.contains(e.relatedTarget))return;handleHoverEnd(item)});container.addEventListener('click',function(e){var item=e.target.closest(itemSelector);if(!item||!container.contains(item))return;e.preventDefault();e.stopPropagation();if(VV_IS_TOUCH_DEVICE){if(vvActiveTouchItem===item){openPost(item);return} 94handleTouchTap(item);return}},!0)} 95function initIsotope(container){if(!window.Isotope){console.warn('[vv-filter] Isotope introuvable â chargez isotope.pkgd.min.js avant ce script.');return null} 96var iso=new window.Isotope(container,{itemSelector:itemSelector,layoutMode:'masonry',percentPosition:!0,masonry:{gutter:VV_GUTTER_PX},hiddenStyle:{opacity:0},visibleStyle:{opacity:1},transitionDuration:VV_TRANSITION_MS+'ms',});function relayout(){iso.layout()} 97if(window.imagesLoaded){window.imagesLoaded(container,relayout)}else{window.addEventListener('load',relayout)} 98bindInteractions(container);if(activeCategory){iso.arrange({filter:'.vv-cat-'+activeCategory});log('Filtre appliqué : '+activeCategory)}else{console.warn("[vv-filter] window.VV_FEED_CATEGORY n'est pas défini â aucune publication ne sera filtrée.")} 99return iso} 100var isotopeInstance=null;function run(){injectStyles();var container=getContainer();if(!container)return!1;var count=categorize(container);if(!count)return!1;if(!isotopeInstance){isotopeInstance=initIsotope(container)}else{if(vvActiveTouchItem){handleHoverEnd(vvActiveTouchItem);vvActiveTouchItem=null} 101container.querySelectorAll('.vv-hover-active').forEach(function(el){handleHoverEnd(el)});isotopeInstance.reloadItems();isotopeInstance.arrange({filter:activeCategory?'.vv-cat-'+activeCategory:'*'})} 102return!0} 103function isOwnMutation(mutations){return mutations.every(function(m){var nodes=[];for(var i=0;i<m.addedNodes.length;i++)nodes.push(m.addedNodes[i]);for(var j=0;j<m.removedNodes.length;j++)nodes.push(m.removedNodes[j]);return nodes.every(function(node){return node.nodeType!==1||(node.classList&&node.classList.contains('vv-hover-video'))})})} 104function start(){injectStyles();if(run()){log('Widget déjà présent au chargement, tri appliqué immédiatement.')} 105var pending=null;var applying=!1;var observer=new MutationObserver(function(mutations){if(applying)return;if(isOwnMutation(mutations))return;if(pending)clearTimeout(pending);pending=setTimeout(function(){pending=null;applying=!0;run();setTimeout(function(){applying=!1},50)},300)});observer.observe(document.body,{childList:!0,subtree:!0});setTimeout(function(){observer.disconnect();log('Observation arrêtée après '+maxWaitMs+'ms.')},maxWaitMs)} 106if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',start)}else{start()}})()
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.