PluginProbe
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News / 4.0.7
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News v4.0.7
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 2.3.5 2.3.6 2.4.0 2.4.1 2.4.10 2.4.11 2.4.12 2.4.13 2.4.14 2.4.15 2.4.16 2.4.17 2.4.18 2.4.19 2.4.2 2.4.20 2.4.21 All 88 releases
post-carousel / blocks / assets / js / news-ticker.js

news-ticker.js in Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News 4.0.7, at blocks/assets/js/news-ticker.js

181 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 document.addEventListener( 'DOMContentLoaded', function () {
2 // news-ticker-slide and fade--------------------------------
3 const sliders = document.querySelectorAll( '.sps-news-ticker-slider' );
4
5 sliders?.forEach( ( slider ) => {
6 const options = JSON.parse(
7 slider.getAttribute( 'data-swiper-options' ) || '{}'
8 );
9 const parentContainer = slider.closest( '.sp-smart-post-swiper' );
10 const pauseButton = parentContainer.querySelector( '.sp-icon-toggle' );
11
12 if ( ! options ) {
13 return;
14 }
15 if ( ! Object.keys( options ).length ) return;
16
17 let tickerSwiper = new PCPSwiper( slider, options );
18 let updateSwiperPause = false;
19 if ( pauseButton ) {
20 pauseButton.addEventListener( 'click', () => {
21 updateSwiperPause = ! updateSwiperPause;
22 if ( updateSwiperPause ) {
23 tickerSwiper.autoplay.stop();
24 } else {
25 tickerSwiper.autoplay.start();
26 }
27 } );
28 }
29 } );
30
31 // news-ticker-ticker--------------------------------
32 const tickers = document.querySelectorAll( '.sp-news-ticker' );
33 tickers?.forEach( ( ticker ) => {
34 const options = JSON.parse(
35 ticker.getAttribute( 'data-options' ) || '{}'
36 );
37
38 const tickerSpeed = parseInt( options.speed ) || 3000;
39 const pxPerSecond = ( 1000 * 250 ) / tickerSpeed;
40 const direction =
41 options.direction === 'left_to_right' ? 'right' : 'left';
42 const pauseOnHover = options.pauseOnHover;
43
44 const wrapper = document.createElement( 'div' );
45 wrapper.classList.add( 'sp-marquee-inner' );
46
47 const originalHTML = ticker.innerHTML;
48 wrapper.innerHTML = originalHTML + originalHTML;
49 ticker.innerHTML = '';
50 ticker.appendChild( wrapper );
51
52 // Ensure inline-block for proper scroll width
53 wrapper.style.whiteSpace = 'nowrap';
54
55 let scrollX = direction === 'left' ? 0 : -wrapper.scrollWidth / 2;
56 let lastTimestamp = null;
57 let rafId;
58
59 function animate( timestamp ) {
60 if ( ! lastTimestamp ) lastTimestamp = timestamp;
61 const delta = ( timestamp - lastTimestamp ) / 1000;
62 lastTimestamp = timestamp;
63
64 const distance = pxPerSecond * delta;
65 scrollX += direction === 'left' ? -distance : distance;
66
67 wrapper.style.transform = `translateX(${ scrollX }px)`;
68
69 // Reset logic based on scroll direction
70 const halfWidth = wrapper.scrollWidth / 2;
71 if ( direction === 'left' && Math.abs( scrollX ) >= halfWidth ) {
72 scrollX = 0;
73 }
74 if ( direction === 'right' && scrollX >= 0 ) {
75 scrollX = -halfWidth;
76 }
77
78 rafId = requestAnimationFrame( animate );
79 }
80
81 rafId = requestAnimationFrame( animate );
82
83 if ( pauseOnHover ) {
84 ticker.addEventListener( 'mouseenter', () => {
85 cancelAnimationFrame( rafId );
86 } );
87 ticker.addEventListener( 'mouseleave', () => {
88 lastTimestamp = null;
89 rafId = requestAnimationFrame( animate );
90 } );
91 }
92 } );
93
94 // news-ticker-typewriter--------------------------------
95 const elements = document.querySelectorAll(
96 '.sps-news-ticker-typewriter-js'
97 );
98
99 elements?.forEach( ( el ) => {
100 const posts = JSON.parse( el.dataset.posts || '[]' );
101 if ( ! posts.length ) return;
102
103 let postIndex = 0;
104 let charIndex = 0;
105 let isDeleting = false;
106 let currentText = '';
107 let lastTime = 0;
108 let delay = 60;
109 const titleEl = el.querySelector( '.sp-smart-post-ticker-title' );
110 const imgEl = el.querySelector( '.sp-ticker-img.sp-img-circle' );
111 //let paused = false; // Default value for Pause on Hover
112
113 // el.addEventListener( 'mouseenter', () => {
114 // paused = true;
115 // } );
116 // el.addEventListener( 'mouseleave', () => {
117 // paused = false;
118 // } );
119 // Preload next image
120 function preloadImage( index ) {
121 const nextIndex = ( index + 1 ) % posts.length;
122 if ( posts[ nextIndex ]?.thumbUrl ) {
123 const img = new Image();
124 img.src = posts[ nextIndex ].thumbUrl;
125 }
126 }
127
128 function updateText( timestamp ) {
129 if ( ! lastTime ) lastTime = timestamp;
130
131 const { title, url, target, thumbUrl } = posts[ postIndex ];
132 // Update image (only when changing posts)
133 if ( ! isDeleting && charIndex === 0 && imgEl && thumbUrl ) {
134 imgEl.style.opacity = '0';
135 setTimeout( () => {
136 imgEl.src = thumbUrl;
137 imgEl.alt = title;
138 imgEl.style.opacity = '1';
139 }, 200 );
140 preloadImage( postIndex );
141 }
142
143 const delta = timestamp - lastTime;
144 if ( delta >= delay ) {
145 // const { title, url, target, thumbUrl } = posts[ postIndex ];
146
147 if ( isDeleting ) {
148 charIndex--;
149 } else {
150 charIndex++;
151 }
152
153 currentText = title.substring( 0, charIndex );
154
155 if ( titleEl ) {
156 titleEl.innerText = currentText; // Update the visible text
157 titleEl.href = url; // Update the link
158 titleEl.target = target || '_self'; // Set target (e.g., _blank)
159 }
160
161 delay = isDeleting ? 20 : 60;
162
163 if ( ! isDeleting && currentText === title ) {
164 delay = 1500; // Pause after full text
165 isDeleting = true;
166 } else if ( isDeleting && charIndex === 0 ) {
167 isDeleting = false;
168 postIndex = ( postIndex + 1 ) % posts.length;
169 delay = 800; // Pause before next word
170 }
171
172 lastTime = timestamp;
173 }
174
175 requestAnimationFrame( updateText );
176 }
177
178 requestAnimationFrame( updateText );
179 } );
180 } );
181