1/** 2 * Represents the Popups object. 3 * @namespace Popups 4 */ 5 6import { CoreEventModels } from './CoreEventModels.js'; 7import { CoreUserModels } from './CoreUserModels.js'; 8import { EventDispatcher } from './EventDispatcher.js'; 9 10/** 11 * Freezes the page behind an open Magnific Popup on mobile. 12 * 13 * Magnific's `fixedContentPos` option defaults to 'auto', which it resolves to `!probablyMobile`, 14 * so on phones it deliberately skips its own scroll lock and leaves the page scrolling behind the 15 * modal â which reads as the popup and the page fighting each other. Uses `position: fixed` on the 16 * body rather than `overflow: hidden`, which iOS Safari ignores. 17 * 18 * @namespace PopupScrollLock 19 */ 20export var PopupScrollLock = { 21 name: 'PopupScrollLock', 22 mobileQuery: '(max-width: 743px)', // tablet breakpoint starts at 744px, per _mediaQueries.scss 23 scrollY: 0, 24 locked: false, 25 observer: null, 26 isMobile: function () { 27 return window.matchMedia(this.mobileQuery).matches; 28 }, 29 lock: function () { 30 if (this.locked || !this.isMobile()) return; 31 this.locked = true; 32 this.scrollY = window.scrollY || document.documentElement.scrollTop; 33 var style = document.body.style; 34 style.position = 'fixed'; 35 style.top = -this.scrollY + 'px'; 36 style.left = '0'; 37 style.right = '0'; 38 style.width = '100%'; 39 }, 40 unlock: function () { 41 if (!this.locked) return; 42 this.locked = false; 43 var style = document.body.style; 44 style.position = ''; 45 style.top = ''; 46 style.left = ''; 47 style.right = ''; 48 style.width = ''; 49 window.scrollTo(0, this.scrollY); 50 }, 51 /** 52 * Watches for Magnific appending/removing its wrapper rather than hooking any one popup's 53 * callbacks, so this covers every component that opens a popup without touching them all. 54 */ 55 install: function () { 56 if (this.observer || !document.body) return; 57 var self = this; 58 this.observer = new MutationObserver(function () { 59 if (document.querySelector('.mfp-wrap')) { 60 self.lock(); 61 } else { 62 self.unlock(); 63 } 64 }); 65 this.observer.observe(document.body, { childList: true }); 66 }, 67}; 68 69PopupScrollLock.install(); 70window.PopupScrollLock = PopupScrollLock; 71 72export var Popups = { 73 name: 'Popups', 74 debugPrefix: `DEBUG | 'Popups.js' | `, 75 debug: false, 76 logStartup: function (message) { 77 console.log(`${this.debugPrefix}message -> '${message}'`); 78 this.debug = true; 79 }, 80 handlePopupOpenEvent: function (event) { 81 let eventName = 'on_popup_open'; 82 this.debug && console.log(`${this.debugPrefix}Starting to handle the '${eventName}' event`, event); 83 this.handlePopupEvent(event, eventName); 84 }, 85 handlePopupCloseEvent: function (event) { 86 let eventName = 'on_popup_close'; 87 this.debug && console.log(`${this.debugPrefix}Starting to handle the '${eventName}' event`, event); 88 this.handlePopupEvent(event, eventName); 89 }, 90 /** 91 * Known popup events. 92 * - Open Modal 93 * 94 * - Video Popup 95 * This may have a YouTube or Vimeo video. 96 * 97 * - Healthy Church From Modal 98 * This loads a HC Form in a modal. 99 * 100 * - Custom HTML Popup 101 */ 102 handlePopupEvent: function (event, eventName) { 103 let eventData = {}; 104 105 this.debug && console.log(`${this.debugPrefix}Raw '${eventName}' event`, event); 106 107 // verify the event source 108 if (event) { 109 let eventTarget = event; 110 111 let enableAnalyticsCollection = 112 (event.getAttribute('data-analytics-enable-collection') || '').toLowerCase() === 'true'; 113 114 // Should we collect data for this event? 115 if (!enableAnalyticsCollection) { 116 this.debug && 117 console.log(`${this.debugPrefix}Analytics collection is disabled for this '${eventName}' event`, event); 118 return; 119 } 120 121 // Analytics Data 122 let analyticsData = CoreEventModels.prepareAnalyticsData( 123 event.getAttribute('data-analytics-enable-collection'), 124 event.getAttribute('data-analytics-use-custom-category'), 125 event.getAttribute('data-analytics-custom-category'), 126 event.getAttribute('data-analytics-use-custom-value'), 127 event.getAttribute('data-analytics-custom-value') 128 ); 129 130 // Popup Event Data 131 let popupData = CoreEventModels.preparePopUpEventData( 132 event.getAttribute('data-action-type'), 133 event.getAttribute('data-video-provider'), 134 event.getAttribute('data-video-url'), 135 event.getAttribute('data-hc-form-type'), 136 event.getAttribute('data-hc-form-id'), 137 event.getAttribute('data-html-modal-title'), 138 event.getAttribute('data-html-modal-text'), 139 event.getAttribute('data-click-element-type'), 140 event.getAttribute('data-click-element-label') 141 ); 142 143 // Page Parameter Data 144 let pageData = CoreEventModels.preparePageParameterData( 145 event.getAttribute('data-page-element-type'), 146 event.getAttribute('data-page-element-title'), 147 window.location.hostname 148 ); 149
150 // combine eventData with popupData 151 eventData = { 152 ...eventData, 153 ...analyticsData, 154 ...popupData, 155 ...pageData, 156 ...this.userData, 157 }; 158 159 eventData['event'] = eventName; 160 } 161 // event source -> unknown 162 else { 163 this.debug && 164 console.log( 165 `${this.debugPrefix}Assuming the trigger for this '${eventName}' event was from an unknown source`, 166 event 167 ); 168 } 169 // Send event data to the analytics service 170 if (eventData && eventData.event) { 171 this.debug && 172 console.log(`${this.debugPrefix}Sending '${eventName}' event data to the analytics service`, eventData); 173 EventDispatcher.sendEvent(eventData); 174 } 175 }, 176}; 177 178window.Popups = Popups;
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.