PageSourceSearch

https://progyny.com/wp-content/themes/favsolution/assets/js/theme.js?ver=1763383918

js progyny.com collected 2026-10-02 03:20:05 UTC 18,717 bytes, 518 lines download raw bytes

1(function() {
2    
3    var navToggle = document.querySelector('.nav-toggle');
4    var searchToggle = document.querySelector('.search-toggle');
5    var navContent = document.querySelector('.header-navigation');
6    var body = document.querySelector('body');
7    var html = document.querySelector('html');
8    var htmlStyle = html.currentStyle || window.getComputedStyle(html);
9    var htmlMarginTop = htmlStyle.marginTop;
10    var menuItemsWithChildren = document.querySelectorAll('.menu-item-has-children > a');
11    var menuItems = document.querySelectorAll('.navigation-wrapper a, .logo a, a.get-started-h, a.login');
12    var footerItems = document.querySelectorAll('.site-footer a');
13    var links = document.querySelectorAll('.site-main a:not([data-placement])');
14    var downloads = document.querySelectorAll('.type-download .actions a');
15    var selects =  document.querySelectorAll('.select');
16    var spacers =  document.querySelectorAll('.fav-spacer');
17    var secondaryMenu =  document.querySelector('.secondary-menu h3');
18    var searchInputs = document.querySelectorAll('.search-field');
19    var searchButtons = document.querySelectorAll('.search-submit');
20    var searchClose = document.querySelector('#search-results .icon-close');
21    var searchTimeout = null;
22    var mixButtons = document.querySelectorAll('[data-placement]');
23    
24    if(window.innerHeight < 1200) {
25        document.getElementById('masthead').style.position = 'static';
26        document.getElementById('masthead').style.position = 'static';
27    }
28    
29    if(searchClose) {
30        searchClose.addEventListener('click', function(event) {
31            body.classList.remove('search-active');
32        });
33    }
34
35    if(searchInputs) {
36        searchInputs.forEach(input => {
37            input.addEventListener('keyup', function(e) {
38                if (e.key == "Enter") {
39                    e.preventDefault();
40                    ajaxSearch(input);
41                } else if(input.value.length > 3) {
42                    clearTimeout(searchTimeout);
43                    searchTimeout = setTimeout( function(){
44                        ajaxSearch(input)
45                    }, 1000);
46                }
47            });
48        });
49    }
50
51    if(searchButtons) {
52        searchButtons.forEach(button => {
53            button.addEventListener('click', function(event) {
54                event.preventDefault();
55            });
56        });
57    }
58
59    if(secondaryMenu) {
60        secondaryMenu.addEventListener('click', function(event) {
61            secondaryMenu.classList.toggle('active');
62            secondaryMenu.nextElementSibling.classList.toggle('active');
63        });
64    }
65
66    spacers.forEach(spacer => {
67        var skip = [
68            'SCRIPT',
69        ];
70        var element = spacer.previousElementSibling;
71        while(element && skip.includes(element.tagName)) {
72            element = element.previousElementSibling;
73        }
74        if(element) {
75            element.style.marginBottom = 0;
76        }
77        
78        element = spacer.nextElementSibling;
79        while(element && skip.includes(element.tagName)) {
80            element = element.nextElementSibling;
81        }
82        if(element) {
83            element.style.marginTop = 0;
84        }
85    });
86
87    selects.forEach(item => {
88        item.querySelector('.icon-down').addEventListener('click', function(event) {
89            item.querySelector('select').click();
90        });
91    });
92
93    // TODO split to functions or files (mobile vs desktop)
94//     if(window.innerWidth < favTheme.mobileBreakpoint) {
95    menuItemsWithChildren.forEach(item => {
96        item.addEventListener('click', function(event) {
97//             if(event.target.nodeName == 'SPAN') {
98//                 return;
99//             }
100            event.preventDefault();
101            var element = event.target.closest('.menu-item-has-children');
102            if(element.classList.contains('active') || element.classList.contains('current-menu-parent')) {
103                element.classList.remove('active');
104                element.classList.remove('current-menu-parent');
105            } else {
106                document.querySelectorAll('.menu-item-has-children > a').forEach(item2 => {
107                    var element2 = item2.closest('.menu-item-has-children');
108                    element2.classList.remove('active');
109                    element2.classList.remove('current-menu-parent');
110                });
111                element.classList.add('active')
112            }
113        });
114    });
115
116//     document.addEventListener('click', function (event) {
117// 
118//         // If the clicked element doesn't have the right selector, bail
119//         if (!event.target.matches('.menu-item-has-children')) return;
120// 
121//         // Don't follow the link
122//         event.preventDefault();
123// 
124//         // Log the clicked element in the console
125//         console.log(event.target);
126// 
127//     }, false);
128
129    navToggle.addEventListener('click', function (event) {
130        event.preventDefault();
131        event.stopPropagation();
132        if(navToggle.classList.contains('active')) {
133            menuHide();
134        } else {
135            menuShow();
136        }
137    });
138
139    searchToggle.addEventListener('click', function (event) {
140        event.preventDefault();
141        event.stopPropagation();
142        showSearchResults([], 'header search');
143    });
144    
145    
146    function menuShow() {
147        navToggle.classList.add('active');
148        navToggle.classList.remove('icon-menu');
149        navToggle.classList.add('icon-close');
150        body.classList.add('menu-active');
151        navToggle.innerHTML = '<span>Explore</span>';
152    }
153    
154    function menuHide() {
155        navToggle.classList.remove('active');
156        navToggle.classList.remove('icon-close');
157        navToggle.classList.add('icon-menu');
158        body.classList.remove('menu-active');
159        navToggle.innerHTML = '<span>Get started</span>';
160    }
161
162    const handleMenuClosure = event => !navContent.contains(event.target) && menuHide()
163
164    window.addEventListener('click', handleMenuClosure)
165    window.addEventListener('focusin', handleMenuClosure)
166    
167    function scrollingClass(event) {
168        var y = window.pageYOffset || document.documentElement.scrollTop;
169        if(y === 0) {
170            document.body.classList.remove('scrolling');
171        } else {
172            document.body.classList.add('scrolling');
173        }
174    }
175    
176    function ajaxSearch(input) {
177        var placement = input.parentElement.getAttribute('aria-label').indexOf("blog") != -1 ? "blog" : "header";
178        var query = input.value;
179        var post_type = input.dataset.postType;
180        const params = new URLSearchParams({
181            action: "fav_search",
182            query: query,
183            post_type: post_type,
184        });
185        fetch(favTheme.adminAjax + '?' + params.toString(), {
186            method: 'GET',
187            headers: {
188                'Content-Type': 'application/json'
189            },
190            referrer: 'no-referrer'
191        }).then(function (response) {
192
193            // The API call was successful!
194            if (response.ok) {
195                return response.json();
196            }
197
198            // There was an error
199            return Promise.reject(response);
200
201        }).then(function (data) {
202            // This is the JSON from our response
203            if(data.success) {
204                showSearchResults(data.data, placement);
205                if(mixpanel) {
206                    mixpanel.track(
207                        "Search Completed",
208                        {
209                            "query": query,
210                            "placement": placement
211                        }
212                    );
213                }
214            }
215        }).catch(function (err) {
216            // There was an error
217            console.warn('Something went wrong.', err);
218        });
219    }
220    
221    function showSearchResults(data, placement=null) {
222        if(!body.classList.contains('search-active')) {
223            body.classList.add('search-active');
224        }
225        document.querySelector('#search-results input').focus();
226        if(placement) {
227            document.querySelector('#search-results form').setAttribute('aria-label', placement);
228        }
229        if(data) {
230            if(data.query) { 
231//                 document.querySelector('#search-results input').value = data.query;
232            }
233            if(data.results) {
234                var results = document.getElementById('search-results-posts');
235                results.parentElement.classList.add('active');
236                results.innerHTML = 'test';
237                var html = '';
238                data.results.forEach(row => {
239                    html += '<div class="result type-' + row.type + '">';
240                    html += row.icon;
241                    html += '<h4>' + row.title + '</h4>';
242                    html += '<div class="h4 lexia">' + row.excerpt + '</div>';
243                    html += '<div class="actions"><a href="'+ row.link +'" class="button link">Read More<i class="icon-arrow-next"></i></a></div>';
244                    html += '</div>';
245                });
246                results.innerHTML = html;
247                if(mixpanel) {
248                    results.querySelectorAll('.button.link')?.forEach((link)=>{
249                        link.addEventListener('click',(event)=>{
250                            mixpanel.track(
251                                "CTA click",
252                                {
253                                    // "destination" : button.getAttribute('href'),
254                                    "destination_Url" : link.getAttribute('href'),
255                                    "placement" : placement,
256                                    "text" : link.textContent,
257                                    "type" : "button",
258                                    // "Location" : button.closest('section').className.replace(/fa-block|.[^\s]*width[^\s]*|\sshape[^\s$]*/, ''),
259                                    // "url" : location.href,
260                                    "source_Url" : location.href
261                                }
262                            );
263                        })
264                    })
265                }
266            } else {
267                var results = document.getElementById('search-results-posts');
268                results.parentElement.classList.remove('active');
269            }
270        } else {
271            document.querySelector('#search-results input').dataset.postType = 'any'
272        }
273    }
274
275    const numSteps = 20.0;
276
277    let increasingColor = "rgba(40, 40, 190, ratio)";
278    let decreasingColor = "rgba(190, 40, 40, ratio)";
279    let animationTargets = document.querySelectorAll('.fav-block[class*="shape-"]:not([class*="-top-"]):not([class*="-bottom-"]) .graphic');
280
281    // Set things up
282    window.addEventListener("load", (event) => {
283
284        createObserver();
285    }, false);
286
287    function createObserver() {
288        let observer;
289
290        let options = {
291            root: null,
292            rootMargin: "0px",
293            threshold: buildThresholdList()
294        };
295
296        observer = new IntersectionObserver(handleIntersect, options);
297        animationTargets.forEach(target => {
298            observer.observe(target);
299        });
300    }
301
302    function buildThresholdList() {
303        let thresholds = [];
304        let numSteps = 20;
305
306        for (let i=1.0; i<=numSteps; i++) {
307            let ratio = i/numSteps;
308            thresholds.push(ratio);
309        }
310
311        thresholds.push(0);
312        return thresholds;
313    }
314    
315    function handleIntersect(entries, observer) {
316        entries.forEach((entry) => {
317            var prevRatio = entry.target.dataset.prevRatio;
318            if(typeof prevRatio == 'undefined') {
319                prevRatio = 0.0;
320            }
321            entry.target.style.opacity = entry.intersectionRatio;
322            entry.target.dataset.prevRatio = entry.intersectionRatio;
323        });
324    }
325    
326    // The parallax function
327    const parallax = elements => {
328        if ('undefined' !== elements && elements.length > 0) {
329            elements.forEach( element => {
330                let y = window.innerHeight - document.getElementById('masthead').offsetHeight - element.getBoundingClientRect().top
331//                 if(element.parentElement.className.includes('fixed')) {
332//                     return;
333//                 }
334                if (y > 0) {
335//                     console.log(y + ' : ' + (0.25 * y));
336                    element.style.transform = 'translate3d(0, ' + (0.1 * y) + 'px ,0)'
337                }
338            })
339        }
340    }
341
342    //If element is in viewport, set its position
343    parallax(animationTargets)
344
345    //Call the function on scroll
346    window.onscroll = () => {
347        parallax(animationTargets)
348    }
349
350    window.addEventListener('scroll', scrollingClass);
351    scrollingClass();
352    
353    if(menuItems) {
354      menuItems.forEach(anchor => {
355        anchor.addEventListener('click', function(event) {
356          if(mixpanel) {
357              mixpanel.track(
358                  "Nav Clicked",
359                  {
360                      "destination_Url" : anchor.getAttribute('href'),
361                      "Text" : anchor.textContent,
362                      "Source_Url" : location.href,
363                      "Type" : "main menu",
364                  }
365              );
366          }
367        });
368      })
369    }
370    if(footerItems) {
371      footerItems.forEach(anchor => {
372        anchor.addEventListener('click', function(event) {
373            if(mixpanel) {
374                event.preventDefault()
375                var a = new RegExp('/' + window.location.host + '/');
376                console.log('Footer click')
377                if (a.test(anchor.getAttribute('href'))) {
378                    mixpanel.track(
379                        "Nav Clicked",
380                        {
381                            "destination_Url" : anchor.getAttribute('href'),
382                            "Text" : anchor.textContent,
383                            "Source_Url" : location.href,
384                            "Type" : "bottom menu",
385                        }
386                    );
387                    location.href = anchor.getAttribute('href')
388                } else {
389                    mixpanel.track(
390                        "Link Clicked",
391                        {
392                            "destination_Url" : anchor.getAttribute('href'),
393                            "Text" : anchor.textContent,
394                            "source_Url" : location.href
395                        }
396                    );
397                    setTimeout(function(){
398                        location.href = anchor.getAttribute('href')
399                    }, 400)
400                }
401            }
402        });
403      })
404    }
405    if(links) {
406      links.forEach(anchor => {
407        anchor.addEventListener('click', function(event) {
408          if(mixpanel) {
409              var a = new RegExp('/' + window.location.host + '/');
410              if (!a.test(anchor.getAttribute('href'))) {
411                event.preventDefault()
412                mixpanel.track(
413                    "Link Clicked",
414                    {
415                        "destination_Url" : anchor.getAttribute('href'),
416                        "Text" : anchor.textContent,
417                        "source_Url" : location.href
418                    }
419                );
420                location.href = anchor.getAttribute('href')
421              }
422          }
423        });
424      })
425    }
426    if(mixButtons) {
427        mixButtons.forEach(button => {
428            button.addEventListener('click', function(event) {
429//                 event.preventDefault();
430                var placement = button.dataset.placement;
431                if(mixpanel) {
432                    mixpanel.track(
433                        "CTA click",
434                        {
435                            // "destination" : button.getAttribute('href'),
436                            "destination_Url" : button.getAttribute('href'),
437                            "placement" : placement,
438                            "text" : button.textContent,
439                            "type" : "button",
440                            // "Location" : button.closest('section').className.replace(/fa-block|.[^\s]*width[^\s]*|\sshape[^\s$]*/, ''),
441                            // "url" : location.href,
442                            "source_Url" : location.href
443                        }
444                    );
445                }
446            });
447        })
448    }
449    if(downloads) {
450        downloads.forEach(button => {
451            button.addEventListener('click', function(event) {
452//                 event.preventDefault();
453                var placement = button.dataset.placement;
454                if(mixpanel) {
455                    mixpanel.track(
456                        "File Downloaded",
457                        {
458                            "file_name" : button.getAttribute('href').split('/').pop(),
459                            "file_type" : button.getAttribute('href').split('.').pop(),
460                            "file_url" : button.getAttribute('href'),
461                            "source_url" : location.href
462                        }
463                    );
464                }
465            });
466        })
467    }
468
469})();
470
471document.addEventListener("DOMContentLoaded", function() {
472    function handleSelectChange(event) {
473        let selectedValue = event.target.value;
474        if (selectedValue) {
475            window.location.href = selectedValue; // Redirect to the selected category or tag archive
476        }
477    }
478
479    document.getElementById("category-select")?.addEventListener("change", handleSelectChange);
480    document.getElementById("tag-select")?.addEventListener("change", handleSelectChange);
481});
482
483document.addEventListener("DOMContentLoaded", (event) => {
484    gsap.registerPlugin(ScrollTrigger)
485    // gsap code here!
486    console.log('gsap')
487    gsap.from('.blog-hero h1', {
488        scrollTrigger: '.blog-hero h1',
489        opacity: 0,
490        y: 50,
491        ease: "power1.out",
492    });
493    gsap.from('.blog-hero .h3', {
494        scrollTrigger: '.blog-hero .h3',
495        opacity: 0,
496        y: 50,
497        delay: 0.2,
498        ease: "power1.out",
499    });
500    gsap.from('.filter-form', {
501        scrollTrigger: '.filter-form',
502        opacity: 0,
503        y: 50,
504        delay: 0.4,
505        ease: "power1.out",
506    });
507    let cardDelay = 0
508    document.querySelectorAll('.post-card')?.forEach((card)=>{
509        gsap.from(card, {
510            scrollTrigger: card,
511            opacity: 0,
512            y: 50,
513            delay: cardDelay,
514            ease: "power1.out",
515        });
516        cardDelay+= 0.1
517    })
518});

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.