PageSourceSearch

https://www.continentalautosports.com/wp-content/themes/dealers/assets/js/dynamic-popup.js?ver=1781177425

js continentalautosports.com collected 2026-09-26 03:26:50 UTC 19,316 bytes, 559 lines download raw bytes

1jQuery(document).ready(function ($) {
2    var vehicleCacheByPostId = {};
3    var pendingByPostId = {};
4
5    function fetchCarData(postID) {
6        var dfd = $.Deferred();
7
8        if (!postID) {
9            dfd.reject('Missing post ID');
10            return dfd.promise();
11        }
12
13        if (!window.wpAjax || !wpAjax.url) {
14            dfd.reject('wpAjax.url is not available');
15            return dfd.promise();
16        }
17
18        $.ajax({
19            url: wpAjax.url,
20            type: 'POST',
21            dataType: 'json',
22            data: {
23                action: 'get_car_popup_data',
24                post_id: postID
25            },
26            success: function (response) {
27                if (!response || !response.success) {
28                    console.error('Car data error:', response ? response.data : 'Invalid response');
29                    dfd.reject(response ? response.data : 'Invalid response');
30                    return;
31                }
32
33                dfd.resolve(response.data);
34            },
35            error: function (xhr, status, error) {
36                console.error('AJAX Error:', status, error);
37                dfd.reject(error || status || 'AJAX error');
38            }
39        });
40
41        return dfd.promise();
42    }
43
44    function loadCarData(postID, type, callback, options) {
45        fetchAndStoreVehicleDetails(postID, type, options).done(function (d) {
46            console.log('Popup Data Loaded:', d);
47            callback(d);
48        });
49    }
50
51    function getVehicleStatus(d, type) {
52        if (type === 'used') {
53            return (d.isCPO && d.isCPO === true) ? 'CPO' : 'Used';
54        }
55
56        return 'New';
57    }
58
59    function buildVehicleDetails(d, type, yearOverride) {
60        return {
61            displayedPrice: d.price || '0',
62            drivetrain: d.drivetrain || 'NA',
63            engine: d.engine || 'NA',
64            exteriorColor: d.exteriorColor || 'NA',
65            fuelType: d.fuelType || 'NA',
66            interiorColor: d.interiorColor || 'NA',
67            make: d.make || '',
68            miles: d.miles || '',
69            model: d.model || '',
70            msrp: d.msrp || '0',
71            postId: d.postId || '',
72            status: getVehicleStatus(d, type),
73            stockNumber: d.stockNumber || '',
74            stockStatus: d.stockStatus || 'on the lot',
75            transmission: d.transmission || 'NA',
76            trim: d.trim || 'NA',
77            vin: d.vin || '',
78            year: yearOverride || d.year || ''
79        };
80    }
81
82    /* --------------------------------------------------------
83       FUNCTION TO UPDATE FORM FIELDS (USED + NEW)
84    -------------------------------------------------------- */
85    function updateFormFields(popup, d, type) {
86        console.log('Updating Form Fields for popup:', popup);
87
88        var status = getVehicleStatus(d, type);
89
90        // Common fields for both used and new
91        popup.find('#form-field-make').val(d.make || '');
92        popup.find('#form-field-model').val(d.model || '');
93        popup.find('#form-field-trim').val(d.trim || '');
94        popup.find('#form-field-status').val(status);
95
96        // Only update these fields for USED cars
97        if (type === 'used') {
98            popup.find('#form-field-year').val(d.year || '');
99            popup.find('#form-field-vin').val(d.vin || '');
100            popup.find('#form-field-miles').val(d.miles || '');
101            popup.find('#form-field-price').val(d.price || '');
102        }
103
104        // Trigger Elementor update
105        popup.find('input').trigger('input').trigger('change');
106
107        console.log('Form fields updated with status:', status);
108    }
109
110    /* --------------------------------------------------------
111       UPDATE POPUP CONTENT (COMMON FUNCTION)
112    -------------------------------------------------------- */
113    function updatePopupContent(popup, d) {
114        popup.find('#popup_car_image img').attr('srcset', d.image).attr('alt', d.model);
115        popup.find('#popup_title .elementor-heading-title').text(d.model);
116        popup.find('#popup_year .elementor-heading-title').text(d.year);
117        popup.find('#popup_miles .elementor-heading-title').text(d.miles + ' Ml');
118        popup.find('#popup_price .elementor-heading-title').text('$ ' + 
118Number(d.price).toLocaleString());
119        popup.find('#popup_dealer_name .elementor-icon-list-text').text(d.dealer);
120
121        console.log('Popup visual content updated');
122    }
123
124    /* --------------------------------------------------------
125       STORE VEHICLE DETAILS IN LOCALSTORAGE + GLOBAL
126    -------------------------------------------------------- */
127    function storeVehicleDetails(d, type, yearOverride) {
128        var vehicleDetails = buildVehicleDetails(d, type, yearOverride);
129
130        localStorage.setItem('vehicleDetails', JSON.stringify(vehicleDetails));
131        window.FerrariVehicleDetails = vehicleDetails;
132
133        if (typeof window.CustomEvent === 'function') {
134            window.dispatchEvent(new CustomEvent('ferrari:vehicle_details_updated', {
135                detail: vehicleDetails
136            }));
137        }
138
139        console.log('Vehicle details stored in localStorage:', vehicleDetails);
140
141        return vehicleDetails;
142    }
143
144    function fetchAndStoreVehicleDetails(postID, type, options) {
145        var dfd = $.Deferred();
146        var opts = options || {};
147        var cacheKey = String(postID);
148
149        if (!opts.force && vehicleCacheByPostId[cacheKey]) {
150            storeVehicleDetails(vehicleCacheByPostId[cacheKey], type, opts.yearOverride);
151            dfd.resolve(vehicleCacheByPostId[cacheKey]);
152            return dfd.promise();
153        }
154
155        if (!opts.force && pendingByPostId[cacheKey]) {
156            return pendingByPostId[cacheKey];
157        }
158
159        pendingByPostId[cacheKey] = dfd.promise();
160
161        fetchCarData(postID)
162            .done(function (d) {
163                d.postId = d.postId || cacheKey;
164                vehicleCacheByPostId[cacheKey] = d;
165                storeVehicleDetails(d, type, opts.yearOverride);
166                dfd.resolve(d);
167            })
168            .fail(function (error) {
169                dfd.reject(error);
170            })
171            .always(function () {
172                delete pendingByPostId[cacheKey];
173            });
174
175        return dfd.promise();
176    }
177
178    function primeVehicleData(postID, type, options) {
179        if (!postID) {
180            return;
181        }
182
183        fetchAndStoreVehicleDetails(postID, type, options).fail(function () {
184            // Silent prefetch failure: click handler still has the normal fetch path.
185        });
186    }
187
188    function isFinanceQuoteTrigger(el) {
189        if (!el || !el.closest) {
190            return false;
191        }
192
193        var trigger = el.closest('.finance-quote, .finance_quote, .cta-finance, [data-finance-quote], a, button, .elementor-button');
194        if (!trigger) {
195            return false;
196        }
197
198        var className = String(trigger.className || '').toLowerCase();
199        var text = String(trigger.textContent || '').replace(/\s+/g, ' ').trim().toLowerCase();
200        var href = String(trigger.getAttribute && trigger.getAttribute('href') || '').toLowerCase();
201
202        return className.indexOf('finance-quote') !== -1 ||
203            className.indexOf('finance_quote') !== -1 ||
204            className.indexOf('cta-finance') !== -1 ||
205            trigger.hasAttribute('data-finance-quote') ||
206            text.indexOf('finance quote') !== -1 ||
207            href.indexOf('finance') !== -1;
208    }
209
210    function setFinanceAutofillIntent() {
211        try {
212            sessionStorage.setItem('vehicleInquiry', 'used');
213            sessionStorage.setItem('fst_vehicle_autofill', '1');
214            sessionStorage.setItem('fst_finance_autofill', '1');
215            console.log('[EELMS] Finance autofill intent set');
216        } catch (e) {
217            console.warn('[EELMS] Failed to set finance inquiry flag:', e);
218        }
219    }
220
221    function interceptPopupOpenUntilDataReady() {
222        document.addEventListener('click', function (event) {
223            var trigger = event.target && event.target.closest ? event.target.closest('.used-car-inquiry, #new-model-inquiry, .new-model-inquiry') : null;
224            var isFinance = false;
225
226            if (!trigger && isFinanceQuoteTrigger(event.target)) {
227                trigger = event.target.closest('.finance-quote, .finance_quote, .cta-finance, [data-finance-quote], a, button, .elementor-button');
228                isFinance = true;
229            }
230
231            if (!trigger) {
232                return;
233            }
234
235            if (trigger.getAttribute('data-fst-popup-ready') === '1') {
236                trigger.removeAttribute('data-fst-popup-ready');
237                if (isFinance) {
238                    setFinanceAutofillIntent();
239                }
240                return;
241            }
242
243            var type = isFinance || trigger.matches('.used-car-inquiry') ? 'used' : 'new';
244            var postID = $(trigger).data('post-id');
245            var options = {};
246
247            if (type === 'new') {
248                options.yearOverride = String(new Date().getFullYear());
249            }
250
251            if (isFinance && !postID) {
252                postID = resolveInventoryPostId();
253            }
254
255            if (!postID && type === 'new') {
256                postID = $(trigger).closest('[data-post-id]').data('post-id') || resolveNewM
256odelPostId();
257            }
258
259            if (!postID) {
260                return;
261            }
262
263            event.preventDefault();
264            event.stopImmediatePropagation();
265
266            fetchAndStoreVehicleDetails(postID, type, options).always(function () {
267                if (isFinance) {
268                    setFinanceAutofillIntent();
269                }
270                trigger.setAttribute('data-fst-popup-ready', '1');
271                trigger.click();
272            });
273        }, true);
274    }
275
276    function resolveNewModelPostId() {
277        var postID = null;
278
279        // Method 1: From body class (WordPress adds postid-XXX class)
280        var bodyClass = $('body').attr('class') || '';
281        var bodyMatch = bodyClass.match(/postid-(\d+)/);
282        if (bodyMatch && bodyMatch[1]) {
283            postID = bodyMatch[1];
284        }
285
286        // Method 2: From article ID
287        if (!postID) {
288            var articleId = $('article[id^="post-"]').first().attr('id');
289            if (articleId) {
290                postID = articleId.replace('post-', '');
291            }
292        }
293
294        // Method 3: From data attribute
295        if (!postID) {
296            postID = $('[data-post-id]').first().data('post-id');
297        }
298
299        // Method 4: From #new-model-inquiry button
300        if (!postID) {
301            postID = $('#new-model-inquiry').data('post-id');
302        }
303
304        return postID;
305    }
306
307    function resolveInventoryPostId() {
308        var postID = null;
309
310        var bodyClass = $('body').attr('class') || '';
311        var bodyMatch = bodyClass.match(/postid-(\d+)/);
312        if (bodyMatch && bodyMatch[1]) {
313            postID = bodyMatch[1];
314        }
315
316        if (!postID) {
317            var articleId = $('article[id^="post-"]').first().attr('id');
318            if (articleId) {
319                postID = articleId.replace('post-', '');
320            }
321        }
322
323        if (!postID) {
324            postID = $('[data-post-id]').first().data('post-id');
325        }
326
327        if (!postID) {
328            postID = $('#used-car-inquiry').data('post-id');
329        }
330
331        return postID;
332    }
333
334    function initNewModelContactTracking() {
335        var currentPath = window.location.pathname || '';
336        if (currentPath.indexOf('/new-model/') === -1) {
337            return;
338        }
339
340        var postID = resolveNewModelPostId();
341        if (!postID) {
342            console.log('[EELMS] No post ID found on new-model page');
343            return;
344        }
345
346        var currentYear = String(new Date().getFullYear());
347
348        console.log('[EELMS] New model post ID:', postID);
349
350        // Initial load for redirects and popup tracking context.
351        fetchAndStoreVehicleDetails(postID, 'new', {
352            yearOverride: currentYear
353        });
354
355        $(document).on('click', 'a[href*="contact"], .contact-us-btn, .contact-button', function (e) {
356            var link = $(this).attr('href');
357
358            // Keep browser behavior for modified clicks/new tabs.
359            if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || this.target === '_blank') {
360                fetchAndStoreVehicleDetails(postID, 'new', {
361                    force: true,
362                    yearOverride: currentYear
363                });
364                return;
365            }
366
367            if (!link || link.charAt(0) === '#' || /^javascript:/i.test(link)) {
368                fetchAndStoreVehicleDetails(postID, 'new', {
369                    force: true,
370                    yearOverride: currentYear
371                });
372                return;
373            }
374
375            e.preventDefault();
376
377            fetchAndStoreVehicleDetails(postID, 'new', {
378                force: true,
379                yearOverride: currentYear
380            }).always(function () {
381                window.location.href = link;
382            });
383        });
384    }
385
386    function initInventoryContactTracking() {
387        var currentPath = String(window.location.pathname || '').toLowerCase();
388        if (currentPath.indexOf('/inventory/') === -1) {
389            return;
390        }
391
392        var postID = resolveInventoryPostId();
393        if (!postID) {
394            console.log('[EELMS] No post ID found on inventory page');
395            return;
396        }
397
398        fetchAndStoreVehicleDetails(postID, 'used');
399    }
400
401    function initVehicleInquiryFlagTracking() {
402        function isAutofillContactLink(link) {
403            var href = String(link || '').toLowerCase();
404            var normalizedHref = href.replace(/\/+#/g, '#');
405            var isContactPage = normalizedHref.indexOf('/about/contact') !== -1 || normalizedHref.indexOf('/contact') !== -1;
406            var hasContactAnchor = normalizedHref.indexOf('#contacts') !== -1 || normalizedHref.indexOf('#contact-us') !== -1;
407
408            return isContactPage && hasContactAnchor;
409        }
410
411        function setAutofillIntentFromVehicleDetails(sourceOverride) {
412            try {
413                var stored = localStorage.getItem('vehicleDetails') || '';
414                if (!stored) return;
415
416                var currentPath = String((window.location && window.location.pathname) || '').toLowerCase();
417                var source = sourceOverride || (currentPath.indexOf('/new-model/') !== -1 ? 'new' : 'used');
418
419                sessionStorage.setItem('vehicleInquiry', source);
420                sessionStorage.setItem('fst_vehicle_autofill', '1');
421                console.log('[EELMS] Vehicle autofill intent set:', source);
422            } catch (e) {
423                console.warn('[EELMS] Failed to set used inquiry flag:', e);
424            }
425        }
426
427        $(document).on('click', '.btn-secondary[href*="contact"], .btn-primary-outline[href*="contact"]', function () {
428            var link = $(this).attr('href');
429            if (!isAutofillContactLink(link)) {
430                return;
431            }
432            var sourceOverride = $(this).hasClass('btn-primary-outline') ? 'new' : '';
433            setAutofillIntentFromVehicleDetails(sourceOverride);
434        });
435    }
436
437    /* --------------------------------------------------------
438       USED CAR POPUP
439    -------------------------------------------------------- */
440    $(document).on('mouseenter focusin touchstart', '.used-car-inquiry', function () {
441        var postID = $(this).data('post-id');
442        if (!postID) {
443            return;
444        }
445
446        primeVehicleData(postID, 'used');
447    });
448
449    $(document).on('click', '.used-car-inquiry', function () {
450        var postID = $(this).data('post-id');
451        if (!postID) {
452            return;
453        }
454
455        loadCarData(postID, 'used', function (d) {
456            var popup = $('.elementor-popup-modal.pre-owned-popup-form');
457
458            if (!popup.length) {
459                console.warn('Used popup not found');
460                return;
461            }
462
463            // Elementor popup loads async — wait 150ms
464            setTimeout(function () {
465                updatePopupContent(popup, d);
466                updateFormFields(popup, d, 'used');
467                storeVehicleDetails(d, 'used');
468            }, 150);
469        });
470    });
471
472    /* --------------------------------------------------------
473       FINANCE POPUP
474    -------------------------------------------------------- */
475    $(document).on('click', '.finance-quote, .finance_quote, .cta-finance, [data-finance-quote]', function () {
476        var postID = $(this).data('post-id') || resolveInventoryPostId();
477        if (!postID) {
478            return;
479        }
480
481        setFinanceAutofillIntent();
482        loadCarData(postID, 'used', function (d) {
483            var popup = $('.elementor-popup-modal.finance-popup-form');
484
485            if (!popup.length) {
486                return;
487            }
488
489            setTimeout(function () {
490                updatePopupContent(popup, d);
491                updateFormFields(popup, d, 'used');
492                storeVehicleDetails(d, 'used');
493            }, 150);
494        });
495    });
496
497    /* --------------------------------------------------------
498       NEW CAR POPUP
499    -------------------------------------------------------- */
500    $(document).on('mouseenter focusin touchstart', '#new-model-inquiry, .new-model-inquiry', function () {
501        var postID = $(this).data('post-id');
502
503        if (!postID) {
504            postID = $(this).closest('[data-post-id]').data('post-id');
505        }
506
507        if (!postID) {
508            postID = resolveNewModelPostId();
509        }
510
511        if (!postID) {
512            return;
513        }
514
515        primeVehicleData(postID, 'new', {
516            yearOverride: String(new Date().getFullYear())
517        });
518    });
519
520    $(document).on('click', '#new-model-inquiry', function () {
521        var postID = $(this).data('post-id');
522
523        // If not found, try parent element (Elementor widget wrapper)
524        if (!postID) {
525            postID = $(this).closest('[data-post-id]').data('post-id');
526        }
527
528        if (!postID) {
529            console.error('No post ID found for new car inquiry');
530            return;
531        }
532
533        loadCarData(postID, 'new', function (d) {
534            var popup = $('.elementor-popup-modal.new-car-popup-form');
535
536            if (!popup.length) {
537                console.warn('New car popup not found');
538                return;
539            }
540
541            // Elementor popup loads async — wait 150ms
542            setTimeout(function () {
543                updatePopupContent(popup, d);
544                updateFormFields(popup, d, 'new');
545                storeVehicleDetails(d, 'new');
546
547                // Update the new car title with model name
548                popup.find('#new-car-title .elementor-heading-title').text('Request more info on the ' + d.model);
549            }, 150);
550        }, {
551            yearOverride: String(new Date().getFullYear())
552        });
553    });
554
555    interceptPopupOpenUntilDataReady();
556    initNewModelContactTracking();
557    initInventoryContactTracking();
558    initVehicleInquiryFlagTracking();
559});

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.