PageSourceSearch

https://www.elsclubdubai.com/wp-content/plugins/cet-wp-plugin-trac…/assets/js/track-tee-times.js?ver=1.0.1

js elsclubdubai.com collected 2026-09-30 21:20:03 UTC 3,912 bytes, 130 lines download raw bytes

1( function () {
2    document.addEventListener( 'DOMContentLoaded', function () {
3
4        /**
5         * This JS function is responsible for tracking form submissions from tee time booking iframes
6         * to push events to Google Tag Manager via dataLayer. It listens for postMessage events from iframes.
7         * 
8         * It covers 2 cases: 
9         * 1) iframe is already present on a page,
10         * 2) iframe is added by a JS script, for this case Mutation Observer is needed
11         */
12        const FormSubmitTracker = {
13            // Configuration
14            iframeUrlParts: [
15                ".svc.golf",
16                ".book.teeitup."
17            ],
18
19            // The event name to listen for in postMessage from iframe
20            EVENT_NAME: "form_submitted",
21
22            // State
23            observer: null,
24            isListening: false,
25
26            // Helpers
27            getIframes() {
28                return Array.from(document.querySelectorAll("iframe"));
29            },
30
31            iframeMatches(iframe) {
32                if (!iframe || !iframe.src) return false;
33
34                return this.iframeUrlParts.some((part) =>
35                    iframe.src.includes(part)
36                );
37            },
38
39            findTargetIframe() {
40                return this.getIframes().find((iframe) =>
41                    this.iframeMatches(iframe)
42                );
43            },
44
45            // Message handler
46            onMessage(event) {
47                const isAllowedOrigin = this.iframeUrlParts.some((part) =>
48                    event.origin.includes(part)
49                );
50
51                if (!isAllowedOrigin) return;
52
53                if (!event.data || event.data.event !== this.EVENT_NAME) return;
54
55                window.dataLayer = Array.isArray(window.dataLayer)
56                    ? window.dataLayer
57                    : [];
58                window.dataLayer.push({
59                    event: this.EVENT_NAME,
60                    formType: event.data.value
61                });
62            },
63
64            // Attach listener once
65            bindListener() {
66                if (this.isListening) return;
67
68                window.addEventListener("message", (e) => this.onMessage(e));
69                this.isListening = true;
70            },
71
72            // Stop observing DOM
73            stopWatching() {
74                if (!this.observer) return;
75
76                this.observer.disconnect();
77                this.observer = null;
78            },
79
80            // Core check logic
81            check() {
82                const targetIframe = this.findTargetIframe();
83
84                if (targetIframe) {
85                    this.bindListener();
86                    this.stopWatching();
87                }
88            },
89
90            // Observe DOM for dynamically added iframes
91            watch() {
92                if (this.observer) return;
93
94                this.observer = new MutationObserver(() => this.check());
95
96                this.observer.observe(document.documentElement, {
97                    childList: true,
98                    subtree: true
99                });
100            },
101
102            // Entry point
103            init(options = {}) {
104                // Allow override of iframeUrlParts
105                if (options.iframeUrlParts) {
106                this.iframeUrlParts = Array.isArray(options.iframeUrlParts)
107                    ? options.iframeUrlParts
108                    : [options.iframeUrlParts];
109                }
110
111                // Initial check
112                this.check();
113
114                // Start observing if not yet matched
115                if (!this.isListening) {
116                    this.watch();
117                }
118            }
119        };
120
121        // Init
122        FormSubmitTracker.init({
123            iframeUrlParts: [
124                ".svc.golf",
125                ".book.teeitup.golf"
126            ]
127        });
128
129    });
130} )();

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.