PageSourceSearch

https://dessertlady.ca/static/version1791040052/frontend/Hyva/Dess…eringmedia_SocialLoginHyva/js/google-gis.js

js dessertlady.ca collected 2026-10-08 07:56:33 UTC 8,174 bytes, 252 lines download raw bytes

1/**
2 * Toweringmedia Social Login — Google Identity Services (Hyvä storefront)
3 *
4 * CSP-safe external script: no inline JS, jQuery, RequireJS, or eval.
5 * Loads https://accounts.google.com/gsi/client once via a shared Promise.
6 * Initializes every [data-tm-google-gis] wrapper on the page.
7 *
8 * Login/register use a Wayfair visual pill with a near-invisible GIS renderButton
9 * hitbox overlay. Account-link wrappers without the overlay still render GIS
10 * into [data-tm-google-gis-button] directly.
11 */
12(function () {
13    'use strict';
14
15    var googleGisPromise = null;
16    var INIT_ATTR = 'data-tm-google-gis-initialized';
17    var OVERLAY_STYLE_ID = 'tm-google-gis-overlay-style';
18
19    /**
20     * Inject Wayfair GIS overlay rules so opacity/hitbox work without a theme CSS rebuild.
21     */
22    function ensureOverlayStyles() {
23        if (document.getElementById(OVERLAY_STYLE_ID)) {
24            return;
25        }
26
27        var style = document.createElement('style');
28        style.id = OVERLAY_STYLE_ID;
29        style.textContent = [
30            '.tm-google-gis-wrapper{position:relative!important;overflow:hidden!important;cursor:pointer!important;}',
31            '.tm-google-gis-hitbox{position:absolute!important;inset:0!important;z-index:2!important;opacity:0.01!important;overflow:hidden!important;}',
32            '.tm-google-gis-hitbox>div{position:absolute!important;inset:0!important;width:100%!important;height:100%!important;}',
33            '.tm-google-gis-hitbox iframe{width:100%!important;min-width:100%!important;height:100%!important;min-height:100%!important;border:0!important;}'
34        ].join('');
35        document.head.appendChild(style);
36    }
37
38    /**
39     * @returns {Promise<void>}
40     */
41    function loadGoogleGis() {
42        if (window.google && window.google.accounts && window.google.accounts.id) {
43            return Promise.resolve();
44        }
45
46        if (googleGisPromise) {
47            return googleGisPromise;
48        }
49
50        googleGisPromise = new Promise(function (resolve, reject) {
51            var script = document.createElement('script');
52            script.src = 'https://accounts.google.com/gsi/client';
53            script.async = true;
54            script.defer = true;
55            script.onload = function () {
56                resolve();
57            };
58            script.onerror = function () {
59                reject(new Error('Failed to load Google GIS client'));
60            };
61            document.head.appendChild(script);
62        });
63
64        return googleGisPromise;
65    }
66
67    /**
68     * @returns {string}
69     */
70    function getFormKey() {
71        var meta = document.querySelector('meta[name="form_key"]');
72
73        if (meta && meta.getAttribute('content')) {
74            return meta.getAttribute('content');
75        }
76
77        if (window.hyva && typeof window.hyva.getFormKey === 'function') {
78            try {
79                return window.hyva.getFormKey() || '';
80            } catch (e) {
81                return '';
82            }
83        }
84
85        return '';
86    }
87
88    /**
89     * @param {HTMLFormElement} form
90     * @param {string} name
91     * @param {string} value
92     */
93    function appendHiddenInput(form, name, value) {
94        if (value === null || value === undefined || value === '') {
95            return;
96        }
97
98        var input = document.createElement('input');
99        input.type = 'hidden';
100        input.name = name;
101        input.value = value;
102        form.appendChild(input);
103    }
104
105    /**
106     * @param {HTMLElement} wrapper
107     * @param {{ credential?: string }} response
108     */
109    function submitCredential(wrapper, response) {
110        if (!response || !response.credential) {
111            return;
112        }
113
114        var callbackUrl = wrapper.dataset.callbackUrl;
115        if (!callbackUrl) {
116            return;
117        }
118
119        var form = document.createElement('form');
120        form.method = 'POST';
121        form.action = callbackUrl;
122
123        appendHiddenInput(form, 'provider', 'google');
124        appendHiddenInput(form, 'credential', response.credential);
125
126        if (wrapper.dataset.returnUrl) {
127            appendHiddenInput(form, 'return_url', wrapper.dataset.returnUrl);
128        }
129
130        if (wrapper.dataset.mode === 'link') {
131            appendHiddenInput(form, 'link_mode', '1');
132        }
133
134        appendHiddenInput(form, 'form_key', getFormKey());
135
136        document.body.appendChild(form);
137        form.submit();
138    }
139
140    /**
141     * @param {HTMLElement} wrapper
142     * @param {HTMLElement} buttonContainer
143     */
144    function renderOverlayButton(wrapper, buttonContainer) {
145        var width = Math.floor(wrapper.getBoundingClientRect().width);
146        if (!width || width < 120) {
147            var configured = parseInt(wrapper.dataset.buttonWidth, 10);
148            width = !Number.isNaN(configured) && configured > 0 ? configured : 320;
149        }
150
151        buttonContainer.replaceChildren();
152        window.google.accounts.id.renderButton(buttonContainer, {
153            type: 'standard',
154            theme: 'outline',
155            size: 'large',
156            shape: 'pill',
157            text: 'continue_with',
158            logo_alignment: 'left',
159            width: width
160        });
161    }
162
163    /**
164     * @param {HTMLElement} wrapper
165     */
166    function initWrapper(wrapper) {
167        if (wrapper.getAttribute(INIT_ATTR) === '1') {
168            return;
169        }
170
171        var clientId = wrapper.dataset.clientId;
172        if (!clientId) {
173            return;
174        }
175
176        wrapper.setAttribute(INIT_ATTR, '1');
177
178        loadGoogleGis().then(function () {
179            if (!window.google || !window.google.accounts || !window.google.accounts.id) {
180                return;
181            }
182
183            var buttonContainer = wrapper.querySelector('[data-tm-google-gis-button]');
184            if (!buttonContainer) {
185                return;
186            }
187
188            window.google.accounts.id.initialize({
189                client_id: clientId,
190                use_fedcm_for_prompt: wrapper.dataset.useFedcm === 'true',
191                callback: function (response) {
192                    submitCredential(wrapper, response);
193                }
194            });
195
196            var usesOverlay = !!wrapper.querySelector('.tm-google-gis-visual');
197
198            if (usesOverlay) {
199                ensureOverlayStyles();
200                renderOverlayButton(wrapper, buttonContainer);
201
202                if (typeof ResizeObserver === 'function') {
203                    var resizeTimer = null;
204                    var observer = new ResizeObserver(function () {
205                        window.clearTimeout(resizeTimer);
206                        resizeTimer = window.setTimeout(function () {
207                            renderOverlayButton(wrapper, buttonContainer);
208                        }, 100);
209                    });
210                    observer.observe(wrapper);
211                }
212            } else {
213                var buttonWidth = parseInt(wrapper.dataset.buttonWidth, 10);
214                if (Number.isNaN(buttonWidth) || buttonWidth <= 0) {
215                    buttonWidth = 220;
216                }
217
218                window.google.accounts.id.renderButton(buttonContainer, {
219                    type: 'standard',
220                    theme: 'outline',
221                    size: 'large',
222                    text: wrapper.dataset.mode === 'link' ? 'continue_with' : 'signin_with',
223                    width: buttonWidth
224                });
225            }
226
227            if (wrapper.dataset.oneTap === 'true') {
228                window.google.accounts.id.prompt();
229            }
230        }).catch(function () {
231            // Fail silently; Facebook/Apple links and OAuth fallbacks remain available.
232        });
233    }
234
235    function initAll() {
236        var wrappers = document.querySelectorAll('[data-tm-google-gis]');
237        if (!wrappers.length) {
238            return;
239        }
240
241        var i;
242        for (i = 0; i < wrappers.length; i++) {
243            initWrapper(wrappers[i]);
244        }
245    }
246
247    if (document.readyState === 'loading') {
248        document.addEventListener('DOMContentLoaded', initAll, { once: true });
249    } else {
250        initAll();
251    }
252})();

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.