PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.14
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.14
2.0.14 2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / sticky-scroll / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.14, at blocks/sticky-scroll/frontend.js

117 lines 3.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 'use strict';
3
4 function reducedMotion() {
5 return window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
6 }
7
8 function initStickyScroll(wrap) {
9 if (wrap.dataset.activate !== '1') return;
10
11 var panels = Array.prototype.slice.call(wrap.querySelectorAll('.bkss-panel'));
12 var imageWrap = wrap.querySelector('.bkss-image-wrap');
13
14 if (!panels.length || !imageWrap) return;
15
16 // Reduced motion: keep all panels fully visible, skip crossfade
17 if (reducedMotion()) {
18 panels.forEach(function (p) { p.classList.add('bkss-active'); });
19 return;
20 }
21
22 var activeIdx = 0;
23
24 function setActive(idx) {
25 if (idx === activeIdx) return;
26 activeIdx = idx;
27 panels.forEach(function (p, i) {
28 p.classList.toggle('bkss-active', i === idx);
29 });
30
31 // Swap pinned image (crossfade)
32 var newUrl = panels[idx].dataset.image || '';
33 var existing = imageWrap.querySelector('img, .bkss-placeholder');
34 if (!newUrl) {
35 if (existing && existing.tagName === 'IMG') {
36 existing.style.opacity = '0.4';
37 }
38 return;
39 }
40
41 // Check if same image
42 if (existing && existing.tagName === 'IMG' && existing.src === newUrl) {
43 existing.style.opacity = '1';
44 return;
45 }
46
47 // Build new image, fade in
48 var img = document.createElement('img');
49 img.src = newUrl;
50 img.alt = '';
51 img.style.width = '100%';
52 img.style.display = 'block';
53 img.style.opacity = '0';
54 img.style.transition = 'opacity 0.35s ease';
55
56 // Copy border-radius from existing image
57 if (existing) {
58 img.style.borderRadius = getComputedStyle(existing).borderRadius;
59 img.style.boxShadow = getComputedStyle(existing).boxShadow;
60 }
61
62 img.onload = function () {
63 // Fade out old, fade in new
64 if (existing) {
65 existing.style.transition = 'opacity 0.2s ease';
66 existing.style.opacity = '0';
67 setTimeout(function () {
68 if (existing.parentNode) existing.parentNode.removeChild(existing);
69 }, 220);
70 }
71 imageWrap.appendChild(img);
72 requestAnimationFrame(function () {
73 img.style.opacity = '1';
74 });
75 };
76 }
77
78 // IntersectionObserver — each panel triggers when it crosses center of viewport
79 var observers = [];
80
81 panels.forEach(function (panel, idx) {
82 var obs = new IntersectionObserver(function (entries) {
83 entries.forEach(function (entry) {
84 if (entry.isIntersecting) {
85 setActive(idx);
86 }
87 });
88 }, { threshold: 0.5, rootMargin: '-20% 0px -20% 0px' });
89
90 obs.observe(panel);
91 observers.push(obs);
92 });
93
94 // Initialise with first panel active
95 panels[0] && panels[0].classList.add('bkss-active');
96 }
97
98 function init() {
99 document.querySelectorAll('.bkss-wrap').forEach(initStickyScroll);
100 }
101
102 if (typeof IntersectionObserver === 'undefined') {
103 // Fallback: show all panels fully
104 document.querySelectorAll('.bkss-panel').forEach(function (p) {
105 p.style.opacity = '1';
106 });
107 return;
108 }
109
110 if (document.readyState === 'loading') {
111 document.addEventListener('DOMContentLoaded', init);
112 } else {
113 init();
114 }
115
116 }());
117