PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.78
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.78
51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 51.1.46 51.1.47 51.1.49 All 37 releases
king-addons / includes / widgets / Login_Register_Form / script.js

script.js in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.78, at includes/widgets/Login_Register_Form/script.js

915 lines 36.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function($) {
2 'use strict';
3
4 // Initialize when Elementor frontend is ready
5 $(window).on('elementor/frontend/init', function() {
6 elementorFrontend.hooks.addAction('frontend/element_ready/king-addons-login-register-form.default', function($scope) {
7 initLoginRegisterForm($scope);
8 });
9 });
10
11 // Initialize for non-Elementor pages
12 $(document).ready(function() {
13 if (typeof elementorFrontend === 'undefined') {
14 $('.king-addons-login-register-form-wrapper').each(function() {
15 initLoginRegisterForm($(this));
16 });
17 }
18 });
19
20 function initLoginRegisterForm($scope) {
21 const $wrapper = $scope.find('.king-addons-login-register-form-wrapper');
22 if (!$wrapper.length) return;
23
24 const $loginForm = $wrapper.find('.king-addons-login-form');
25 const $registerForm = $wrapper.find('.king-addons-register-form');
26 const widgetId = $wrapper.data('widget-id');
27 const isAjaxEnabled = $wrapper.data('ajax') === true;
28
29 // Get widget settings from data attributes
30 const widgetSettings = {
31 recaptcha_score_threshold: $wrapper.data('recaptcha-threshold') || '0.5',
32 redirect_after_login: $wrapper.data('redirect-login') || '',
33 redirect_after_register: $wrapper.data('redirect-register') || '',
34 terms_required: $wrapper.data('terms-required') || 'no',
35 enable_user_email: $wrapper.data('enable-user-email') || 'yes',
36 user_email_subject: $wrapper.data('user-email-subject') || '',
37 user_email_content: $wrapper.data('user-email-content') || '',
38 enable_admin_email: $wrapper.data('enable-admin-email') || 'no',
39 admin_email_address: $wrapper.data('admin-email-address') || '',
40 admin_email_subject: $wrapper.data('admin-email-subject') || '',
41 admin_email_content: $wrapper.data('admin-email-content') || '',
42 enable_mailchimp_integration: $wrapper.data('enable-mailchimp') || 'no',
43 auto_login_after_register: $wrapper.data('auto-login') || 'yes'
44 };
45
46 // Form toggle functionality
47 initFormToggle($wrapper, $loginForm, $registerForm);
48
49 // AJAX form submission
50 if (isAjaxEnabled) {
51 const $lostPasswordForm = $wrapper.find('.king-addons-lost-password-form');
52 initAjaxForms($wrapper, $loginForm, $registerForm, $lostPasswordForm, widgetId, widgetSettings);
53 }
54
55 // Form validation
56 initFormValidation($loginForm, $registerForm);
57
58 // Password visibility toggle
59 initPasswordToggle($wrapper);
60
61 // Social login
62 initSocialLogin($wrapper);
63
64 // reCAPTCHA initialization
65 initRecaptcha($wrapper);
66 }
67
68 function initFormToggle($wrapper, $loginForm, $registerForm) {
69 $wrapper.on('click', '.king-addons-form-toggle', function(e) {
70 e.preventDefault();
71
72 const toggleType = $(this).data('toggle');
73 const $lostPasswordForm = $wrapper.find('.king-addons-lost-password-form');
74
75 let $targetForm;
76 if (toggleType === 'login') {
77 $targetForm = $loginForm;
78 } else if (toggleType === 'register') {
79 $targetForm = $registerForm;
80 } else if (toggleType === 'lostpassword') {
81 $targetForm = $lostPasswordForm;
82 }
83
84 if (!$targetForm) return;
85
86 // Clear any existing messages
87 clearMessages($wrapper);
88
89 // Hide all forms
90 $loginForm.hide();
91 $registerForm.hide();
92 $lostPasswordForm.hide();
93
94 // Show target form
95 $targetForm.show();
96 });
97 }
98
99 function initAjaxForms($wrapper, $loginForm, $registerForm, $lostPasswordForm, widgetId, widgetSettings) {
100 // Login form submission
101 $loginForm.find('form').on('submit', function(e) {
102 e.preventDefault();
103 handleLoginSubmission($(this), $wrapper, widgetId, widgetSettings);
104 });
105
106 // Register form submission
107 $registerForm.find('form').on('submit', function(e) {
108 e.preventDefault();
109 handleRegisterSubmission($(this), $wrapper, widgetId, widgetSettings);
110 });
111
112 // Lost password form submission
113 if ($lostPasswordForm.length) {
114 $lostPasswordForm.find('form').on('submit', function(e) {
115 e.preventDefault();
116 handleLostPasswordSubmission($(this), $wrapper, widgetId);
117 });
118 }
119 }
120
121 function handleLoginSubmission($form, $wrapper, widgetId, widgetSettings) {
122 const $messageContainer = $form.closest('.king-addons-login-register-form').find('.king-addons-form-message');
123 const $submitButton = $form.find('.king-addons-login-button');
124 const postId = $wrapper.data('post-id') || 0;
125
126 // Clear previous messages
127 clearMessages($wrapper);
128
129 // Check if variables are defined
130 if (typeof king_addons_login_register_vars === 'undefined') {
131 // console.error('King Addons Login Register: AJAX variables not loaded');
132 showMessage($messageContainer, 'Configuration error. Please refresh the page.', 'error');
133 return;
134 }
135
136 // Get form data
137 const formData = {
138 action: 'king_addons_user_login',
139 nonce: king_addons_login_register_vars.login_nonce,
140 username: $form.find('[name="username"]').val(),
141 password: $form.find('[name="password"]').val(),
142 remember: $form.find('[name="remember"]').is(':checked') ? 1 : 0,
143 widget_id: widgetId,
144 post_id: postId,
145 recaptcha_score_threshold: widgetSettings.recaptcha_score_threshold,
146 redirect_after_login: widgetSettings.redirect_after_login
147 };
148
149 // Add reCAPTCHA response if present
150 const recaptchaResponse = $form.find('[name="g-recaptcha-response"]').val();
151 if (recaptchaResponse) {
152 formData['g-recaptcha-response'] = recaptchaResponse;
153 }
154
155 // console.log('Submitting login form with data:', formData);
156
157 // Validate required fields
158 if (!formData.username || !formData.password) {
159 showMessage($messageContainer, 'Please fill in all required fields.', 'error');
160 return;
161 }
162
163 // Show loading state
164 setLoadingState($form, true);
165 $submitButton.prop('disabled', true);
166
167 // Submit via AJAX
168 $.ajax({
169 url: king_addons_login_register_vars.ajax_url,
170 type: 'POST',
171 data: formData,
172 success: function(response) {
173 if (response.success) {
174 showMessage($messageContainer, response.data.message, 'success');
175
176 // Redirect if URL provided
177 if (response.data.redirect) {
178 setTimeout(function() {
179 window.location.href = response.data.redirect;
180 }, 1500);
181 } else {
182 // Reload page
183 setTimeout(function() {
184 location.reload();
185 }, 1500);
186 }
187 } else {
188 showMessage($messageContainer, response.data.message || 'An error occurred. Please try again.', 'error');
189 }
190 },
191 error: function(xhr, status, error) {
192 // console.error('Login AJAX Error:', error);
193 // console.error('Login XHR response:', xhr.responseText);
194 // console.error('Login XHR status code:', xhr.status);
195
196 let errorMessage = 'Network error. Please check your connection and try again.';
197
198 // Try to parse error response
199 try {
200 const response = JSON.parse(xhr.responseText);
201 if (response.data && response.data.message) {
202 errorMessage = response.data.message;
203 }
204 } catch (e) {
205 // Use default error message
206 }
207
208 showMessage($messageContainer, errorMessage, 'error');
209 },
210 complete: function() {
211 setLoadingState($form, false);
212 $submitButton.prop('disabled', false);
213 }
214 });
215 }
216
217 function handleRegisterSubmission($form, $wrapper, widgetId, widgetSettings) {
218 const $messageContainer = $form.closest('.king-addons-login-register-form').find('.king-addons-form-message');
219 const $submitButton = $form.find('.king-addons-register-button');
220 const postId = $wrapper.data('post-id') || 0;
221
222 // Clear previous messages
223 clearMessages($wrapper);
224
225 // Check if variables are defined
226 if (typeof king_addons_login_register_vars === 'undefined') {
227 // console.error('King Addons Login Register: AJAX variables not loaded');
228 showMessage($messageContainer, 'Configuration error. Please refresh the page.', 'error');
229 return;
230 }
231
232 // Get form data
233 const formData = {
234 action: 'king_addons_user_register',
235 nonce: king_addons_login_register_vars.register_nonce,
236 email: $form.find('[name="email"]').val(),
237 username: $form.find('[name="username"]').val(),
238 password: $form.find('[name="password"]').val(),
239 confirm_password: $form.find('[name="confirm_password"]').val(),
240 widget_id: widgetId,
241 post_id: postId,
242 recaptcha_score_threshold: widgetSettings.recaptcha_score_threshold,
243 redirect_after_register: widgetSettings.redirect_after_register,
244 terms_required: widgetSettings.terms_required,
245 enable_user_email: widgetSettings.enable_user_email,
246 user_email_subject: widgetSettings.user_email_subject,
247 user_email_content: widgetSettings.user_email_content,
248 enable_admin_email: widgetSettings.enable_admin_email,
249 admin_email_address: widgetSettings.admin_email_address,
250 admin_email_subject: widgetSettings.admin_email_subject,
251 admin_email_content: widgetSettings.admin_email_content,
252 enable_mailchimp_integration: widgetSettings.enable_mailchimp_integration,
253 auto_login_after_register: widgetSettings.auto_login_after_register
254 };
255
256 // Add additional fields if they exist
257 const firstName = $form.find('[name="first_name"]').val();
258 const lastName = $form.find('[name="last_name"]').val();
259 const website = $form.find('[name="website"]').val();
260 const phone = $form.find('[name="phone"]').val();
261 const userRole = $form.find('[name="user_role"]').val();
262 const termsConditions = $form.find('[name="terms_conditions"]').is(':checked');
263
264 if (firstName) formData.first_name = firstName;
265 if (lastName) formData.last_name = lastName;
266 if (website) formData.website = website;
267 if (phone) formData.phone = phone;
268 if (userRole) formData.user_role = userRole;
269 if (termsConditions) formData.terms_conditions = 1;
270
271 // Collect custom fields from repeater
272 const customFields = {};
273 const customFieldLabels = {};
274
275 $form.find('[name^="custom_field_"]').each(function() {
276 const fieldName = $(this).attr('name');
277 const fieldType = $(this).attr('type');
278 const fieldLabel = $(this).closest('.king-addons-form-field').data('field-label') || fieldName.replace('custom_field_', 'Field ');
279 let fieldValue;
280
281 if (fieldType === 'checkbox') {
282 // For checkboxes, collect all checked values
283 const checkedBoxes = $form.find('[name="' + fieldName + '"]:checked');
284 if (checkedBoxes.length > 0) {
285 const values = [];
286 checkedBoxes.each(function() {
287 values.push($(this).val());
288 });
289 fieldValue = values.length === 1 ? values[0] : values;
290 }
291 } else if (fieldType === 'radio') {
292 // For radio buttons, get the checked value
293 fieldValue = $form.find('[name="' + fieldName + '"]:checked').val();
294 } else {
295 // For other input types (text, email, etc.)
296 fieldValue = $(this).val();
297 }
298
299 if (fieldValue && fieldValue !== '') {
300 customFields[fieldName] = fieldValue;
301 customFieldLabels[fieldName] = fieldLabel;
302 }
303 });
304
305 // Also handle textarea and select fields
306 $form.find('textarea[name^="custom_field_"], select[name^="custom_field_"]').each(function() {
307 const fieldName = $(this).attr('name');
308 const fieldValue = $(this).val();
309 const fieldLabel = $(this).closest('.king-addons-form-field').data('field-label') || fieldName.replace('custom_field_', 'Field ');
310
311 if (fieldValue && fieldValue !== '') {
312 customFields[fieldName] = fieldValue;
313 customFieldLabels[fieldName] = fieldLabel;
314 }
315 });
316
317 // Add custom fields to form data if any exist
318 if (Object.keys(customFields).length > 0) {
319 formData.custom_fields = customFields;
320 formData.custom_field_labels = customFieldLabels;
321 // console.log('Found custom fields:', customFields);
322 // console.log('Field labels:', customFieldLabels);
323 } else {
324 // console.log('No custom fields found');
325 }
326
327 // Add reCAPTCHA response if present
328 const recaptchaResponse = $form.find('[name="g-recaptcha-response"]').val();
329 if (recaptchaResponse) {
330 formData['g-recaptcha-response'] = recaptchaResponse;
331 }
332
333 // console.log('Submitting registration form with data:', formData);
334
335 // Client-side validation
336 const validationResult = validateRegistrationForm(formData);
337 if (!validationResult.valid) {
338 showMessage($messageContainer, validationResult.message, 'error');
339 return;
340 }
341
342 // Show loading state
343 setLoadingState($form, true);
344 $submitButton.prop('disabled', true);
345
346 // Prepare FormData for file uploads
347 let ajaxData = formData;
348 let ajaxOptions = {
349 url: king_addons_login_register_vars.ajax_url,
350 type: 'POST',
351 data: ajaxData,
352 };
353
354 // Check if there are file inputs
355 const $fileInputs = $form.find('input[type="file"]');
356 if ($fileInputs.length > 0) {
357 // Use FormData for file uploads
358 const formDataObj = new FormData();
359
360 // Add all form data
361 for (const key in formData) {
362 if (formData.hasOwnProperty(key)) {
363 if (typeof formData[key] === 'object' && formData[key] !== null) {
364 formDataObj.append(key, JSON.stringify(formData[key]));
365 } else {
366 formDataObj.append(key, formData[key]);
367 }
368 }
369 }
370
371 // Add files
372 $fileInputs.each(function() {
373 const $input = $(this);
374 const files = $input[0].files;
375 if (files.length > 0) {
376 for (let i = 0; i < files.length; i++) {
377 formDataObj.append($input.attr('name'), files[i]);
378 }
379 }
380 });
381
382 ajaxOptions.data = formDataObj;
383 ajaxOptions.processData = false;
384 ajaxOptions.contentType = false;
385 }
386
387 // Submit via AJAX
388 $.ajax(ajaxOptions).done(function(response) {
389 if (response.success) {
390 showMessage($messageContainer, response.data.message, 'success');
391
392 // Redirect if URL provided
393 if (response.data.redirect) {
394 setTimeout(function() {
395 window.location.href = response.data.redirect;
396 }, 1500);
397 } else {
398 // Reload page or switch to login form
399 setTimeout(function() {
400 location.reload();
401 }, 1500);
402 }
403 } else {
404 showMessage($messageContainer, response.data.message || 'Registration failed. Please try again.', 'error');
405 }
406 }).fail(function(xhr, status, error) {
407 // console.error('Registration AJAX Error:', error);
408 // console.error('Registration XHR response:', xhr.responseText);
409 // console.error('Registration XHR status code:', xhr.status);
410
411 let errorMessage = 'Network error. Please check your connection and try again.';
412
413 // Try to parse error response
414 try {
415 const response = JSON.parse(xhr.responseText);
416 if (response.data && response.data.message) {
417 errorMessage = response.data.message;
418 }
419 } catch (e) {
420 // Use default error message
421 }
422
423 showMessage($messageContainer, errorMessage, 'error');
424 }).always(function() {
425 setLoadingState($form, false);
426 $submitButton.prop('disabled', false);
427 });
428 }
429
430 function handleLostPasswordSubmission($form, $wrapper, widgetId) {
431 const $messageContainer = $form.closest('.king-addons-lost-password-form').find('.king-addons-form-message');
432 const $submitButton = $form.find('.king-addons-lostpassword-button');
433
434 // Clear previous messages
435 clearMessages($wrapper);
436
437 // Check if variables are defined
438 if (typeof king_addons_login_register_vars === 'undefined') {
439 // console.error('King Addons Login Register: AJAX variables not loaded');
440 showMessage($messageContainer, 'Configuration error. Please refresh the page.', 'error');
441 return;
442 }
443
444 // Get form data
445 const formData = {
446 action: 'king_addons_user_lostpassword',
447 nonce: king_addons_login_register_vars.lostpassword_nonce,
448 user_login: $form.find('[name="user_login"]').val(),
449 widget_id: widgetId
450 };
451
452 // Validate required fields
453 if (!formData.user_login) {
454 showMessage($messageContainer, 'Please enter your email address.', 'error');
455 return;
456 }
457
458 // Show loading state
459 setLoadingState($form, true);
460 $submitButton.prop('disabled', true);
461
462 // Submit via AJAX
463 $.ajax({
464 url: king_addons_login_register_vars.ajax_url,
465 type: 'POST',
466 data: formData,
467 timeout: 30000,
468 success: function(response) {
469 if (response.success) {
470 showMessage($messageContainer, response.data.message, 'success');
471 $form[0].reset(); // Clear the form
472 } else {
473 showMessage($messageContainer, response.data.message || 'Lost password request failed. Please try again.', 'error');
474 }
475 },
476 error: function(xhr, status, error) {
477 // console.error('Lost Password AJAX Error:', error);
478 // console.error('Lost Password XHR response:', xhr.responseText);
479 // console.error('Lost Password XHR status code:', xhr.status);
480
481 let errorMessage = 'Network error. Please check your connection and try again.';
482
483 // Try to parse error response
484 try {
485 const response = JSON.parse(xhr.responseText);
486 if (response.data && response.data.message) {
487 errorMessage = response.data.message;
488 }
489 } catch (e) {
490 // Use default error message
491 }
492
493 showMessage($messageContainer, errorMessage, 'error');
494 },
495 complete: function() {
496 setLoadingState($form, false);
497 $submitButton.prop('disabled', false);
498 }
499 });
500 }
501
502 function validateRegistrationForm(data) {
503 // Check required fields
504 if (!data.email || !data.username || !data.password || !data.confirm_password) {
505 return {
506 valid: false,
507 message: 'Please fill in all required fields.'
508 };
509 }
510
511 // Validate email format
512 const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
513 if (!emailRegex.test(data.email)) {
514 return {
515 valid: false,
516 message: 'Please enter a valid email address.'
517 };
518 }
519
520 // Validate username (basic validation)
521 if (data.username.length < 3) {
522 return {
523 valid: false,
524 message: 'Username must be at least 3 characters long.'
525 };
526 }
527
528 // Check username characters
529 const usernameRegex = /^[a-zA-Z0-9._-]+$/;
530 if (!usernameRegex.test(data.username)) {
531 return {
532 valid: false,
533 message: 'Username can only contain letters, numbers, periods, hyphens, and underscores.'
534 };
535 }
536
537 // Validate password length
538 if (data.password.length < 6) {
539 return {
540 valid: false,
541 message: 'Password must be at least 6 characters long.'
542 };
543 }
544
545 // Enhanced password strength validation (updated for security)
546 if (data.password.length < 8) {
547 return {
548 valid: false,
549 message: 'Password must be at least 8 characters long.'
550 };
551 }
552
553 // Check for basic password strength
554 const hasLower = /[a-z]/.test(data.password);
555 const hasUpper = /[A-Z]/.test(data.password);
556 const hasNumbers = /\d/.test(data.password);
557 const hasSpecial = /[!@#$%^&*(),.?":{}|<>]/.test(data.password);
558
559 let strengthScore = 0;
560 if (hasLower) strengthScore++;
561 if (hasUpper) strengthScore++;
562 if (hasNumbers) strengthScore++;
563 if (hasSpecial) strengthScore++;
564
565 if (strengthScore < 3) {
566 return {
567 valid: false,
568 message: 'Password must contain uppercase, lowercase, numbers, and special characters for security.'
569 };
570 }
571
572 // Check against common passwords
573 const commonPasswords = ['password', '123456', '123456789', 'qwerty', 'abc123', 'password123'];
574 if (commonPasswords.includes(data.password.toLowerCase())) {
575 return {
576 valid: false,
577 message: 'Please choose a more unique password. This password is too common.'
578 };
579 }
580
581 // Check password confirmation
582 if (data.password !== data.confirm_password) {
583 return {
584 valid: false,
585 message: 'Passwords do not match.'
586 };
587 }
588
589 // Check terms and conditions if required
590 const $termsCheckbox = $('.king-addons-register-form [name="terms_conditions"]');
591 if ($termsCheckbox.length && $termsCheckbox.prop('required') && !$termsCheckbox.is(':checked')) {
592 return {
593 valid: false,
594 message: 'Please accept the Terms & Conditions.'
595 };
596 }
597
598 return { valid: true };
599 }
600
601 function initFormValidation($loginForm, $registerForm) {
602 // Real-time validation for registration form
603 $registerForm.find('[name="confirm_password"]').on('blur keyup', function() {
604 const password = $registerForm.find('[name="password"]').val();
605 const confirmPassword = $(this).val();
606 const $field = $(this).closest('.king-addons-form-field');
607
608 // Remove existing validation classes
609 $field.removeClass('field-error field-success');
610
611 if (confirmPassword && password && password !== confirmPassword) {
612 $field.addClass('field-error');
613 showFieldError($field, 'Passwords do not match.');
614 } else if (confirmPassword && password && password === confirmPassword) {
615 $field.addClass('field-success');
616 hideFieldError($field);
617 } else {
618 hideFieldError($field);
619 }
620 });
621
622 // Email validation
623 $registerForm.find('[name="email"]').on('blur', function() {
624 const email = $(this).val();
625 const $field = $(this).closest('.king-addons-form-field');
626 const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
627
628 $field.removeClass('field-error field-success');
629
630 if (email && !emailRegex.test(email)) {
631 $field.addClass('field-error');
632 showFieldError($field, 'Please enter a valid email address.');
633 } else if (email) {
634 $field.addClass('field-success');
635 hideFieldError($field);
636 } else {
637 hideFieldError($field);
638 }
639 });
640
641 // Username validation
642 $registerForm.find('[name="username"]').on('blur', function() {
643 const username = $(this).val();
644 const $field = $(this).closest('.king-addons-form-field');
645 const usernameRegex = /^[a-zA-Z0-9._-]+$/;
646
647 $field.removeClass('field-error field-success');
648
649 if (username && (username.length < 3 || !usernameRegex.test(username))) {
650 $field.addClass('field-error');
651 const message = username.length < 3
652 ? 'Username must be at least 3 characters long.'
653 : 'Username can only contain letters, numbers, periods, hyphens, and underscores.';
654 showFieldError($field, message);
655 } else if (username) {
656 $field.addClass('field-success');
657 hideFieldError($field);
658 } else {
659 hideFieldError($field);
660 }
661 });
662 }
663
664 function showFieldError($field, message) {
665 hideFieldError($field);
666 $field.append('<span class="field-error-message" style="color: #f44336; font-size: 12px; margin-top: 5px; display: block;">' + message + '</span>');
667 }
668
669 function hideFieldError($field) {
670 $field.find('.field-error-message').remove();
671 }
672
673 function initPasswordToggle($wrapper) {
674 $wrapper.on('click', '.king-addons-password-toggle', function(e) {
675 e.preventDefault();
676
677 const $button = $(this);
678 const $input = $button.siblings('input[type="password"], input[type="text"]');
679 const $icon = $button.find('.king-addons-password-toggle-icon');
680
681 if ($input.attr('type') === 'password') {
682 $input.attr('type', 'text');
683 $icon.text('🙈');
684 $button.attr('aria-label', 'Hide password');
685 } else {
686 $input.attr('type', 'password');
687 $icon.text('👁');
688 $button.attr('aria-label', 'Show password');
689 }
690 });
691 }
692
693 function showMessage($container, message, type) {
694 $container.removeClass('success error').addClass(type + ' show').text(message);
695
696 // Auto-hide success messages after 5 seconds
697 if (type === 'success') {
698 setTimeout(function() {
699 $container.removeClass('show');
700 }, 5000);
701 }
702 }
703
704 function clearMessages($wrapper) {
705 $wrapper.find('.king-addons-form-message').removeClass('success error show').text('');
706 }
707
708 function setLoadingState($form, loading) {
709 if (loading) {
710 $form.addClass('king-addons-form-loading');
711 } else {
712 $form.removeClass('king-addons-form-loading');
713 }
714 }
715
716 function initSocialLogin($wrapper) {
717 // Google login
718 $wrapper.find('.king-addons-google-login').on('click', function(e) {
719 e.preventDefault();
720 const $button = $(this);
721 const clientId = $button.data('client-id');
722
723 if (!clientId) {
724 showSocialLoginError('Google Client ID not configured. Please check widget settings.');
725 return;
726 }
727
728 // Check if Google API is loaded
729 if (typeof google === 'undefined' || !google.accounts) {
730 showSocialLoginError('Google API not loaded. Please check your internet connection.');
731 return;
732 }
733
734 // Initialize Google One Tap
735 google.accounts.id.initialize({
736 client_id: clientId,
737 callback: handleGoogleResponse,
738 auto_select: false,
739 cancel_on_tap_outside: true
740 });
741
742 // Show Google login prompt
743 google.accounts.id.prompt();
744 });
745
746 // Facebook login
747 $wrapper.find('.king-addons-facebook-login').on('click', function(e) {
748 e.preventDefault();
749 const $button = $(this);
750 const appId = $button.data('app-id');
751
752 if (!appId) {
753 showSocialLoginError('Facebook App ID not configured. Please check widget settings.');
754 return;
755 }
756
757 // Check if Facebook SDK is loaded
758 if (typeof FB === 'undefined') {
759 showSocialLoginError('Facebook SDK not loaded. Please check your internet connection.');
760 return;
761 }
762
763 // Facebook login
764 FB.login(function(response) {
765 if (response.authResponse) {
766 handleFacebookResponse(response.authResponse);
767 } else {
768 showSocialLoginError('Facebook login was cancelled or failed.');
769 }
770 }, {scope: 'email,public_profile'});
771 });
772
773 function handleGoogleResponse(response) {
774 const $wrapper = $('.king-addons-login-register-form-wrapper');
775 const widgetId = $wrapper.data('widget-id');
776 const $messageContainer = $wrapper.find('.king-addons-form-message');
777
778 // Show loading
779 showMessage($messageContainer, 'Authenticating with Google...', 'info');
780
781 $.ajax({
782 url: king_addons_login_register_vars.ajax_url,
783 type: 'POST',
784 data: {
785 action: 'king_addons_google_login',
786 nonce: king_addons_login_register_vars.social_login_nonce,
787 google_token: response.credential,
788 widget_id: widgetId,
789 post_id: $wrapper.data('post-id') || 0
790 },
791 success: function(ajaxResponse) {
792 if (ajaxResponse.success) {
793 showMessage($messageContainer, ajaxResponse.data.message, 'success');
794 if (ajaxResponse.data.redirect) {
795 setTimeout(() => {
796 window.location.href = ajaxResponse.data.redirect;
797 }, 1500);
798 } else {
799 setTimeout(() => {
800 location.reload();
801 }, 1500);
802 }
803 } else {
804 showMessage($messageContainer, ajaxResponse.data.message, 'error');
805 }
806 },
807 error: function() {
808 showMessage($messageContainer, 'Google login failed. Please try again.', 'error');
809 }
810 });
811 }
812
813 function handleFacebookResponse(authResponse) {
814 const $wrapper = $('.king-addons-login-register-form-wrapper');
815 const widgetId = $wrapper.data('widget-id');
816 const $messageContainer = $wrapper.find('.king-addons-form-message');
817
818 // Show loading
819 showMessage($messageContainer, 'Authenticating with Facebook...', 'info');
820
821 $.ajax({
822 url: king_addons_login_register_vars.ajax_url,
823 type: 'POST',
824 data: {
825 action: 'king_addons_facebook_login',
826 nonce: king_addons_login_register_vars.social_login_nonce,
827 facebook_token: authResponse.accessToken,
828 widget_id: widgetId,
829 post_id: $wrapper.data('post-id') || 0
830 },
831 success: function(ajaxResponse) {
832 if (ajaxResponse.success) {
833 showMessage($messageContainer, ajaxResponse.data.message, 'success');
834 if (ajaxResponse.data.redirect) {
835 setTimeout(() => {
836 window.location.href = ajaxResponse.data.redirect;
837 }, 1500);
838 } else {
839 setTimeout(() => {
840 location.reload();
841 }, 1500);
842 }
843 } else {
844 showMessage($messageContainer, ajaxResponse.data.message, 'error');
845 }
846 },
847 error: function() {
848 showMessage($messageContainer, 'Facebook login failed. Please try again.', 'error');
849 }
850 });
851 }
852
853 function showSocialLoginError(message) {
854 const $wrapper = $('.king-addons-login-register-form-wrapper');
855 const $messageContainer = $wrapper.find('.king-addons-form-message');
856 showMessage($messageContainer, message, 'error');
857 }
858 }
859
860 function initRecaptcha($wrapper) {
861 // Initialize reCAPTCHA v2
862 $wrapper.find('.king-addons-recaptcha-v2').each(function() {
863 const $recaptcha = $(this);
864 const sitekey = $recaptcha.data('sitekey');
865 const theme = $recaptcha.data('theme') || 'light';
866 const size = $recaptcha.data('size') || 'normal';
867
868 if (typeof grecaptcha !== 'undefined' && sitekey) {
869 grecaptcha.ready(function() {
870 grecaptcha.render($recaptcha[0], {
871 'sitekey': sitekey,
872 'theme': theme,
873 'size': size
874 });
875 });
876 }
877 });
878
879 // For reCAPTCHA v3, we'll handle it in form submission
880 $wrapper.find('.king-addons-recaptcha-v3').each(function() {
881 const $recaptcha = $(this);
882 const sitekey = $recaptcha.data('sitekey');
883 const action = $recaptcha.data('action');
884
885 if (typeof grecaptcha !== 'undefined' && sitekey) {
886 // v3 tokens are generated on form submission
887 $recaptcha.closest('form').on('submit', function(e) {
888 const $form = $(this);
889
890 if ($recaptcha.val()) {
891 // Token already exists, proceed
892 return;
893 }
894
895 e.preventDefault();
896
897 grecaptcha.ready(function() {
898 grecaptcha.execute(sitekey, {action: action}).then(function(token) {
899 $recaptcha.val(token);
900 $form.trigger('submit');
901 });
902 });
903 });
904 }
905 });
906 }
907
908 // Expose functions globally for potential external use
909 window.KingAddonsLoginRegister = {
910 initForm: initLoginRegisterForm,
911 showMessage: showMessage,
912 clearMessages: clearMessages
913 };
914
915 })(jQuery);