PageSourceSearch

https://heystudio.es/wp-content/plugins/mailchimp-newsletter-manager/assets/js/newsletter.js?ver=1790910773

js heystudio.es collected 2026-10-02 03:13:11 UTC 19,137 bytes, 598 lines download raw bytes

1/**
2 * JavaScript para formularios de newsletter
3 * Compatible con la estructura HTML existente del tema
4 * 
5 * @package MailchimpNewsletterManager
6 * @since 1.0.0
7 */
8
9(function($) {
10    'use strict';
11
12    /**
13     * Clase principal para manejo de formularios de newsletter
14     */
15    class NewsletterForm {
16        constructor(form) {
17            this.form = $(form);
18            this.emailInput = this.form.find('.newsletter_email');
19            this.submitButton = this.form.find('.newsletter_submit');
20            this.errorDiv = this.form.find('.newsletter_error');
21            this.thanksDiv = this.form.find('.newsletter_thanks_wrapper');
22            this.formInputs = this.form.find('.newsletter_form_inputs');
23            
24            // Verificar que los elementos existen
25            if (!this.errorDiv.length) {
26                this.errorDiv = $('<div class="newsletter_error" style="margin-top: 15px; min-height: 50px; opacity: 0;"></div>');
27                this.form.append(this.errorDiv);
28            }
29            if (!this.thanksDiv.length) {
30                this.thanksDiv = $('<div class="newsletter_thanks_wrapper" style="margin-top: 15px; min-height: 50px; opacity: 0;"></div>');
31                this.form.append(this.thanksDiv);
32            }
33            
34            this.init();
35        }
36
37        init() {
38            this.bindEvents();
39            this.setupValidation();
40        }
41
42        bindEvents() {
43            // Validación en tiempo real del email
44            this.emailInput.on('input', () => {
45                this.validateEmail();
46            });
47
48            // Envío del formulario
49            this.form.on('submit', (e) => {
50                e.preventDefault();
51                this.handleSubmit();
52            });
53
54            // Limpiar mensajes al escribir
55            this.emailInput.on('input', () => {
56                this.hideMessages();
57            });
58        }
59
60        setupValidation() {
61            // Validación inicial
62            this.validateEmail();
63        }
64
65        validateEmail() {
66            const email = this.emailInput.val();
67            const isValid = this.isValidEmail(email);
68            
69            if (email && !isValid) {
70                this.emailInput.addClass('error');
71                this.submitButton.prop('disabled', true);
72            } else if (email && isValid) {
73                this.emailInput.removeClass('error');
74                this.submitButton.prop('disabled', false);
75            } else {
76                this.emailInput.removeClass('error');
77                this.submitButton.prop('disabled', true);
78            }
79        }
80
81        isValidEmail(email) {
82            const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
83            return emailRegex.test(email);
84        }
85
86        handleSubmit() {
87            const email = this.emailInput.val();
88
89            // Validación final
90            if (!email || !this.isValidEmail(email)) {
91                this.showError(mailchimpNewsletter.messages.invalid_email);
92                return;
93            }
94
95            // Mostrar estado de carga
96            this.setLoadingState(true);
97            this.hideMessages();
98
99            // Preparar datos
100            const formData = {
101                action: 'newsletter_subscribe',
102                nonce: mailchimpNewsletter.nonce,
103                email: email,
104                source: 'wordpress-form'
105            };
106
107            // Enviar petición AJAX
108            $.ajax({
109                url: mailchimpNewsletter.ajaxUrl,
110                type: 'POST',
111                data: formData,
112                timeout: 30000,
113                success: (response) => {
114                    this.handleResponse(response);
115                },
116                error: (xhr, status, error) => {
117                    this.handleError(status, error);
118                },
119                complete: () => {
120                    this.setLoadingState(false);
121                }
122            });
123        }
124
125        handleResponse(response) {
126            console.log("=== HANDLERESPONSE EJECUTÁNDOSE ===");
127            console.log("Response completa:", response);
128            console.log("Response.success:", response.success);
129            
130            if (response.success) {
131                console.log("Llamando showSuccess()");
132                this.showSuccess();
133                this.resetForm();
134                this.trackEvent('success', {
135                    email: this.emailInput.val(),
136                    source: 'wordpress-form'
137                });
138            } else {
139                console.log("Llamando showError()");
140                this.showError(response.data.message || mailchimpNewsletter.messages.error);
141                this.trackEvent('error', {
142                    email: this.emailInput.val(),
143                    error: response.data.message,
144                    source: 'wordpress-form'
145                });
146            }
147        }
148
149        handleError(status, error) {
150            let errorMessage = mailchimpNewsletter.messages.error;
151            
152            if (status === 'timeout') {
153                errorMessage = 'La petición tardó demasiado. Inténtalo de nuevo.';
154            } else if (status === 'abort') {
155                errorMessage = 'La petición fue cancelada.';
156            } else if (error) {
157                errorMessage = `Error de red: ${error}`;
158            }
159
160            this.showError(errorMessage);
161            this.trackEvent('error', {
162                email: this.emailInput.val(),
163                error: errorMessage,
164                source: 'wordpress-form'
165            });
166        }
167
168        showError(message) {
169            this.errorDiv.text(message).addClass("show");
170            this.thanksDiv.removeClass("show");
171            this.formInputs.addClass('error');
172            
173            // Scroll al error si es necesario
174            this.scrollToError();
175        }
176
177        showSuccess() {
178            this.errorDiv.removeClass("show");
179            this.thanksDiv.text(mailchimpNewsletter.messages.success || '¡Gracias por suscribirte!').addClass("show");
180            this.formInputs.removeClass('error');
181        }
182
183        hideMessages() {
184            this.errorDiv.removeClass("show");
185            this.thanksDiv.removeClass("show");
186            this.formInputs.removeClass('error');
187        }
188
189        setLoadingState(loading) {
190            if (loading) {
191                this.submitButton
192                    .prop('disabled', true)
193                    .addClass('loading')
194                    .val(mailchimpNewsletter.messages.loading);
195            } else {
196                this.submitButton
197                    .prop('disabled', false)
198                    .removeClass('loading')
199                    .val('Subscribe'); // Texto original del botón
200            }
201        }
202
203        resetForm() {
204            this.form[0].reset();
205            this.submitButton.prop('disabled', true);
206            this.hideMessages();
207        }
208
209        scrollToError() {
210            if (this.errorDiv.length && this.errorDiv.is(':visible')) {
211                const errorTop = this.errorDiv.offset().top;
212                const windowTop = $(window).scrollTop();
213                const windowHeight = $(window).height();
214                
215                if (errorTop < windowTop || errorTop > windowTop + windowHeight) {
216                    $('html, body').animate({
217                        scrollTop: errorTop - 100
218                    }, 300);
219                }
220            }
221        }
222
223        trackEvent(eventName, parameters = {}) {
224            // Google Analytics 4
225            if (typeof gtag !== 'undefined') {
226                gtag('event', `newsletter_${eventName}`, {
227                    event_category: 'engagement',
228                    event_label: parameters.source || 'wordpress-form',
229                    value: parameters.email ? 1 : 0,
230                    ...parameters
231                });
232            }
233
234            // Facebook Pixel
235            if (typeof fbq !== 'undefined') {
236                if (eventName === 'success') {
237                    fbq('track', 'CompleteRegistration', {
238                        content_name: 'Newsletter Subscription',
239                        content_category: 'Email Marketing',
240                        ...parameters
241                    });
242                } else if (eventName === 'error') {
243                    fbq('track', 'Lead', {
244                        content_name: 'Newsletter Subscription Attempt',
245                        content_category: 'Email Marketing',
246                        ...parameters
247                    });
248                }
249            }
250
251            // Evento personalizado para otros sistemas de tracking
252            $(document).trigger('newsletter:event', [eventName, parameters]);
253        }
254    }
255
256    /**
257     * Clase para formularios minimalistas
258     */
259    class MinimalNewsletterForm {
260        constructor(form) {
261            this.form = $(form);
262            this.emailInput = this.form.find('.newsletter_email_minimal');
263            this.submitButton = this.form.find('.newsletter_submit_minimal');
264            
265            this.init();
266        }
267
268        init() {
269            this.bindEvents();
270        }
271
272        bindEvents() {
273            this.form.on('submit', (e) => {
274                e.preventDefault();
275                this.handleSubmit();
276            });
277        }
278
279        handleSubmit() {
280            const email = this.emailInput.val();
281            
282            if (!email || !this.isValidEmail(email)) {
283                this.emailInput.focus();
284                return;
285            }
286
287            this.setLoadingState(true);
288
289            $.ajax({
290                url: mailchimpNewsletter.ajaxUrl,
291                type: 'POST',
292                data: {
293                    action: 'newsletter_subscribe',
294                    nonce: mailchimpNewsletter.nonce,
295                    email: email,
296                    source: 'minimal-form'
297                },
298                success: (response) => {
299                    if (response.success) {
300                        this.showSuccess();
301                        this.resetForm();
302                    } else {
303                        this.showError(response.data.message);
304                    }
305                },
306                error: () => {
307                    this.showError('Error de conexión');
308                },
309                complete: () => {
310                    this.setLoadingState(false);
311                }
312            });
313        }
314
315        isValidEmail(email) {
316            const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
317            return emailRegex.test(email);
318        }
319
320        setLoadingState(loading) {
321            if (loading) {
322                this.submitButton.prop('disabled', true).text('...');
323            } else {
324                this.submitButton.prop('disabled', false).text('Subscribe');
325            }
326        }
327
328        showSuccess() {
329            this.submitButton.text('✓ Subscribed!');
330            setTimeout(() => {
331                this.submitButton.text('Subscribe');
332            }, 3000);
333        }
334
335        showError(message) {
336            const originalText = this.submitButton.text();
337            this.submitButton.text('Error');
338            setTimeout(() => {
339                this.submitButton.text(originalText);
340            }, 2000);
341        }
342
343        resetForm() {
344            this.form[0].reset();
345        }
346    }
347
348    /**
349     * Clase para popups de newsletter
350     */
351    class NewsletterPopup {
352        constructor(popup) {
353            this.popup = $(popup);
354            this.overlay = this.popup.find('.newsletter_popup_overlay');
355            this.closeBtn = this.popup.find('.newsletter_popup_close');
356            this.form = this.popup.find('.newsletter_popup_form');
357            this.emailInput = this.form.find('.newsletter_popup_email');
358            this.nameInput = this.form.find('.newsletter_popup_name');
359            this.submitButton = this.form.find('.newsletter_popup_submit');
360            
361            this.shown = false;
362            this.init();
363        }
364
365        init() {
366            this.bindEvents();
367            this.setupTriggers();
368        }
369
370        bindEvents() {
371            // Cerrar popup
372            this.closeBtn.on('click', () => {
373                this.hide();
374            });
375
376            this.overlay.on('click', (e) => {
377                if (e.target === this.overlay[0]) {
378                    this.hide();
379                }
380            });
381
382            // Envío del formulario
383            this.form.on('submit', (e) => {
384                e.preventDefault();
385                this.handleSubmit();
386            });
387
388            // Cerrar con Escape
389            $(document).on('keydown', (e) => {
390                if (e.key === 'Escape' && this.overlay.is(':visible')) {
391                    this.hide();
392                }
393            });
394        }
395
396        setupTriggers() {
397            // Verificar si ya se mostró el popup
398            if (localStorage.getItem('newsletter_popup_shown') === 'true') {
399                return;
400            }
401
402            // Trigger por tiempo
403            const delay = parseInt(this.popup.data('delay')) || 5000;
404            setTimeout(() => {
405                this.show();
406            }, delay);
407
408            // Trigger por scroll
409            const scrollPercent = parseInt(this.popup.data('scroll-percent')) || 50;
410            $(window).on('scroll', () => {
411                const scrollTop = $(window).scrollTop();
412                const docHeight = $(document).height();
413                const winHeight = $(window).height();
414                const scrollPercentActual = (scrollTop / (docHeight - winHeight)) * 100;
415                
416                if (scrollPercentActual >= scrollPercent) {
417                    this.show();
418                    $(window).off('scroll');
419                }
420            });
421
422            // Trigger por exit intent
423            $(document).on('mouseleave', (e) => {
424                if (e.clientY <= 0) {
425                    this.show();
426                    $(document).off('mouseleave');
427                }
428            });
429        }
430
431        show() {
432            if (this.shown) return;
433            
434            this.overlay.fadeIn(300);
435            this.shown = true;
436            localStorage.setItem('newsletter_popup_shown', 'true');
437            
438            // Focus en el primer input
439            setTimeout(() => {
440                this.emailInput.focus();
441            }, 350);
442        }
443
444        hide() {
445            this.overlay.fadeOut(300);
446        }
447
448        handleSubmit() {
449            const email = this.emailInput.val();
450            const name = this.nameInput.length ? this.nameInput.val() : '';
451
452            if (!email || !this.isValidEmail(email)) {
453                this.emailInput.focus();
454                return;
455            }
456
457            this.setLoadingState(true);
458
459            $.ajax({
460                url: mailchimpNewsletter.ajaxUrl,
461                type: 'POST',
462                data: {
463                    action: 'newsletter_subscribe',
464                    nonce: mailchimpNewsletter.nonce,
465                    email: email,
466                    name: name,
467                    source: 'popup-form'
468                },
469                success: (response) => {
470                    if (response.success) {
471                        this.showSuccess();
472                        setTimeout(() => {
473                            this.hide();
474                        }, 2000);
475                    } else {
476                        this.showError(response.data.message);
477                    }
478                },
479                error: () => {
480                    this.showError('Error de conexión');
481                },
482                complete: () => {
483                    this.setLoadingState(false);
484                }
485            });
486        }
487
488        isValidEmail(email) {
489            const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
490            return emailRegex.test(email);
491        }
492
493        setLoadingState(loading) {
494            if (loading) {
495                this.submitButton.prop('disabled', true).text('Subscribing...');
496            } else {
497                this.submitButton.prop('disabled', false).text('Subscribe');
498            }
499        }
500
501        showSuccess() {
502            this.submitButton.text('✓ Subscribed!');
503        }
504
505        showError(message) {
506            const originalText = this.submitButton.text();
507            this.submitButton.text('Error');
508            setTimeout(() => {
509                this.submitButton.text(originalText);
510            }, 2000);
511        }
512    }
513
514    /**
515     * Utilidades globales
516     */
517    window.MailchimpNewsletter = {
518        // Suscribir programáticamente
519        subscribe: function(email, name = '', source = 'api') {
520            return $.ajax({
521                url: mailchimpNewsletter.ajaxUrl,
522                type: 'POST',
523                data: {
524                    action: 'newsletter_subscribe',
525                    nonce: mailchimpNewsletter.nonce,
526                    email: email,
527                    name: name,
528                    source: source
529                }
530            });
531        },
532
533        // Eventos personalizados
534        onSuccess: function(callback) {
535            $(document).on('newsletter:event', function(e, eventName, parameters) {
536                if (eventName === 'success') {
537                    callback(parameters);
538                }
539            });
540        },
541
542        onError: function(callback) {
543            $(document).on('newsletter:event', function(e, eventName, parameters) {
544                if (eventName === 'error') {
545                    callback(parameters);
546                }
547            });
548        }
549    };
550
551    /**
552     * Inicialización cuando el DOM está listo
553     */
554    $(document).ready(function() {
555        // Inicializar formularios estándar
556        $('.newsletter_form').each(function() {
557            new NewsletterForm(this);
558        });
559
560        // Inicializar formularios minimalistas
561        $('.newsletter_form_minimal').each(function() {
562            new MinimalNewsletterForm(this);
563        });
564
565        // Inicializar popups
566        $('.newsletter_popup_overlay').each(function() {
567            new NewsletterPopup(this);
568        });
569
570        // Rate limiting básico
571        let lastSubmission = 0;
572        const minInterval = 2000; // 2 segundos entre envíos
573
574        $(document).on('submit', '.newsletter_form, .newsletter_form_minimal, .newsletter_popup_form', function(e) {
575            const now = Date.now();
576            if (now - lastSubmission < minInterval) {
577                e.preventDefault();
578                return false;
579            }
580            lastSubmission = now;
581        });
582    });
583
584    /**
585     * Manejo de errores globales
586     */
587    window.addEventListener('error', function(e) {
588        console.error('Newsletter Form Error:', e.error);
589    });
590
591    /**
592     * Manejo de promesas rechazadas
593     */
594    window.addEventListener('unhandledrejection', function(e) {
595        console.error('Newsletter Form Promise Rejection:', e.reason);
596    });
597
598})(jQuery);

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.