PluginProbe
Block Animations, Motion & Scroll Effects – Ghost Kit / 2.25.0
Block Animations, Motion & Scroll Effects – Ghost Kit v2.25.0
3.7.2 3.7.1 3.7.0 3.6.1 trunk 1.6.3 2.25.0 3.3.0 3.3.1 3.3.2 3.3.3 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.5.0 3.5.1 3.6.0
ghostkit / assets / js / main.js

main.js in Block Animations, Motion & Scroll Effects – Ghost Kit 2.25.0, at assets/js/main.js

308 lines 8.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * External dependencies
3 */
4 import { throttle } from 'throttle-debounce';
5 import rafSchd from 'raf-schd';
6
7 /**
8 * Internal dependencies
9 */
10 import parseSRConfig from '../../gutenberg/extend/scroll-reveal/parseSRConfig';
11
12 const $ = window.jQuery;
13
14 const { ghostkitVariables, GHOSTKIT } = window;
15
16 class GhostKitClass {
17 constructor() {
18 const self = this;
19
20 self.isMobile = /Android|iPhone|iPad|iPod|BlackBerry|Windows Phone/g.test(
21 window.navigator.userAgent || window.navigator.vendor || window.opera
22 );
23
24 // prepare media vars.
25 self.screenSizes = [];
26 Object.keys(ghostkitVariables.media_sizes).forEach((k) => {
27 self.screenSizes.push(ghostkitVariables.media_sizes[k]);
28 });
29
30 self.customStyles = $('#ghostkit-blocks-custom-css-inline-css').html() || '';
31
32 // Methods bind class.
33 self.initBlocks = self.initBlocks.bind(self);
34 self.prepareCounters = self.prepareCounters.bind(self);
35 self.prepareFallbackCustomStyles = self.prepareFallbackCustomStyles.bind(self);
36 self.prepareSR = self.prepareSR.bind(self);
37 self.getWnd = self.getWnd.bind(self);
38
39 GHOSTKIT.triggerEvent('beforeInit', self);
40
41 // Additional easing.
42 $.extend($.easing, {
43 easeOutCubic(x) {
44 return 1 - (1 - x) ** 3;
45 },
46 });
47
48 // Init blocks.
49 const throttledInitBlocks = throttle(
50 200,
51 rafSchd(() => {
52 self.initBlocks();
53 })
54 );
55 if (window.MutationObserver) {
56 new window.MutationObserver(throttledInitBlocks).observe(document.documentElement, {
57 childList: true,
58 subtree: true,
59 });
60 } else {
61 $(document).on('DOMContentLoaded DOMNodeInserted load', () => {
62 throttledInitBlocks();
63 });
64 }
65
66 GHOSTKIT.triggerEvent('afterInit', self);
67 }
68
69 // Init blocks.
70 initBlocks() {
71 const self = this;
72
73 GHOSTKIT.triggerEvent('beforeInitBlocks', self);
74
75 GHOSTKIT.triggerEvent('initBlocks', self);
76
77 self.prepareFallbackCustomStyles();
78 self.prepareNumberedLists();
79 self.prepareCounters();
80 self.prepareSR();
81
82 GHOSTKIT.triggerEvent('afterInitBlocks', self);
83 }
84
85 // Get window size.
86 // eslint-disable-next-line class-methods-use-this
87 getWnd() {
88 // eslint-disable-next-line no-console
89 console.warn(
90 'GHOSTKIT.getWnd method is deprecated since v2.9.0 and will be removed in future updates. Please, use `window.innerWidth` and `window.innerHeight`'
91 );
92
93 return {
94 w: window.innerWidth,
95 h: window.innerHeight,
96 };
97 }
98
99 /**
100 * Prepare Numbered Lists with `start` attribute.
101 */
102 prepareNumberedLists() {
103 const self = this;
104
105 GHOSTKIT.triggerEvent('beforePrepareNumberedLists', self);
106
107 $('.is-style-styled:not(.is-style-styled-ready)').each(function () {
108 const $this = $(this);
109 const start = parseInt($this.attr('start'), 10);
110 const isReversed = typeof $this.attr('reversed') !== 'undefined';
111 const itemsCount = $this.children().length;
112
113 $this.addClass('is-style-styled-ready');
114
115 if (isReversed) {
116 $this.css('counter-reset', `li ${(start || itemsCount) + 1}`);
117 } else if (start) {
118 $this.css('counter-reset', `li ${start - 1}`);
119 }
120 });
121
122 GHOSTKIT.triggerEvent('afterPrepareNumberedLists', self);
123 }
124
125 /**
126 * Prepare Counters (Number Box, Progress Bar)
127 */
128 prepareCounters() {
129 const self = this;
130
131 GHOSTKIT.triggerEvent('beforePrepareCounters', self);
132
133 $('.ghostkit-count-up:not(.ghostkit-count-up-ready)').each(function () {
134 const $this = $(this);
135 const isProgress = $this.hasClass('ghostkit-progress-bar');
136 const from = parseFloat($this.attr('data-count-from')) || 0;
137 const to = parseFloat(isProgress ? $this.attr('aria-valuenow') : $this.text()) || 0;
138 let $progressCountBadgeWrap;
139 let $progressCountBadge;
140
141 // prepare mask.
142 let mask = '';
143 if (!isProgress) {
144 // eslint-disable-next-line no-template-curly-in-string
145 mask = $this.text().replace(to, '${val}');
146 }
147 if (!/\${val}/.test(mask)) {
148 // eslint-disable-next-line no-template-curly-in-string
149 mask = '${val}';
150 }
151
152 $this.addClass('ghostkit-count-up-ready');
153
154 if (isProgress) {
155 $progressCountBadgeWrap = $this
156 .closest('.ghostkit-progress')
157 .find('.ghostkit-progress-bar-count');
158 $progressCountBadge = $progressCountBadgeWrap.find('> div > span:eq(1)');
159
160 $progressCountBadgeWrap.css('width', '0%');
161 $progressCountBadge.text('0');
162 $this.css('width', '0%');
163 } else {
164 // eslint-disable-next-line no-template-curly-in-string
165 $this.text(mask.replace('${val}', from));
166 }
167
168 const item = {
169 $el: $this,
170 el: this,
171 from,
172 to,
173 duration: 1000,
174 easing: 'easeOutCubic',
175 cb(num) {
176 if (isProgress) {
177 $this.css('width', `${Math.ceil(num * 100) / 100}%`);
178 $progressCountBadgeWrap.css('width', `${Math.ceil(num * 100) / 100}%`);
179
180 $progressCountBadge.text(Math.ceil(num));
181 } else {
182 // eslint-disable-next-line no-template-curly-in-string
183 $this.text(mask.replace('${val}', Math.ceil(num)));
184 }
185 },
186 };
187
188 GHOSTKIT.triggerEvent('prepareCounters', self, item);
189
190 // Run counter.
191 if (!('IntersectionObserver' in window)) {
192 item.cb(item.to, true);
193 return;
194 }
195
196 const countersObserverData = {
197 callback: (entries, observer) => {
198 entries.forEach((entry) => {
199 if (entry.isIntersecting && item.el === entry.target) {
200 observer.unobserve(entry.target);
201
202 $({ Counter: item.from }).animate(
203 { Counter: item.to },
204 {
205 duration: item.duration,
206 easing: item.easing,
207 step() {
208 item.cb(this.Counter, false);
209 },
210 complete() {
211 item.cb(item.to, true);
212 GHOSTKIT.triggerEvent('animatedCounters', self, item);
213 },
214 }
215 );
216 }
217 });
218 },
219 options: {
220 // We have to start the animation only when part of the block is visible on the screen.
221 rootMargin: '-50px',
222 },
223 };
224
225 GHOSTKIT.triggerEvent('prepareCountersObserver', self, countersObserverData);
226
227 const countersObserver = new IntersectionObserver(
228 countersObserverData.callback,
229 countersObserverData.options
230 );
231
232 countersObserver.observe(item.el);
233 });
234
235 GHOSTKIT.triggerEvent('afterPrepareCounters', self);
236 }
237
238 /**
239 * Prepare custom styles.
240 * This method used as Fallback only.
241 * Since plugin version 2.6.0 we use PHP styles render.
242 */
243 prepareFallbackCustomStyles() {
244 const self = this;
245 let reloadStyles = false;
246
247 GHOSTKIT.triggerEvent('beforePrepareCustomStyles', self);
248
249 $('[data-ghostkit-styles]').each(function () {
250 const $this = $(this);
251 self.customStyles += GHOSTKIT.replaceVars($this.attr('data-ghostkit-styles'));
252 $this.removeAttr('data-ghostkit-styles');
253 reloadStyles = true;
254 });
255
256 if (reloadStyles) {
257 let $style = $('#ghostkit-blocks-custom-css-inline-css');
258 if (!$style.length) {
259 $style = $('<style id="ghostkit-blocks-custom-css-inline-css">').appendTo('head');
260 }
261 $style.html(self.customStyles);
262 }
263
264 GHOSTKIT.triggerEvent('afterPrepareCustomStyles', self);
265 }
266
267 /**
268 * Prepare ScrollReveal
269 */
270 prepareSR() {
271 const self = this;
272
273 if (!window.ScrollReveal) {
274 return;
275 }
276
277 const { reveal } = window.ScrollReveal();
278
279 GHOSTKIT.triggerEvent('beforePrepareSR', self);
280
281 $('[data-ghostkit-sr]:not(.data-ghostkit-sr-ready)').each(function () {
282 const $element = $(this);
283
284 GHOSTKIT.triggerEvent('beforePrepareSRStart', self, $element);
285
286 $element.addClass('data-ghostkit-sr-ready');
287
288 const data = $element.attr('data-ghostkit-sr');
289 const config = parseSRConfig(data);
290
291 config.afterReveal = () => {
292 $element.removeAttr('data-ghostkit-sr');
293 $element.removeClass('data-ghostkit-sr-ready');
294 };
295
296 GHOSTKIT.triggerEvent('beforeInitSR', self, $element, config);
297
298 reveal(this, config);
299
300 GHOSTKIT.triggerEvent('beforePrepareSREnd', self, $element);
301 });
302
303 GHOSTKIT.triggerEvent('afterPrepareSR', self);
304 }
305 }
306
307 GHOSTKIT.classObject = new GhostKitClass();
308