PluginProbe ʕ •ᴥ•ʔ
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin / 4.9.0
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin v4.9.0
4.9.0 0.9.6 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.2 1.7.0 1.7.1 1.8.0 1.8.1 1.9.0 2.0.0 2.0.1 2.1.1 2.2.1 2.3.1 2.4.0 2.5.0 2.5.1 2.6.0 2.7.0 2.8.0 2.9.0 3.0.1 3.0.2 3.0.3 3.1.0 3.10.0 3.11.0 3.11.1 3.2.0 3.2.1 3.3.0 3.4.0 3.5.0 3.5.1 3.5.2 3.6.1 3.7.0 3.8.0 3.8.2 3.9.0 4.0.1 4.1.0 4.1.1 4.2.0 4.3.0 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.8.0 trunk 0.10.0 0.10.1 0.11.1 0.11.2 0.3.1 0.3.2 0.4 0.4.1 0.4.2 0.5.0 0.5.1 0.5.2 0.6 0.7 0.8 0.8.2 0.8.3 0.8.4 0.8.5 0.8.6 0.8.7 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5
wp-mail-smtp / assets / js / smtp-admin.js
wp-mail-smtp / assets / js Last commit date
vendor 5 days ago connect.js 5 days ago connect.min.js 5 days ago smtp-about.js 5 days ago smtp-about.min.js 5 days ago smtp-activelayer-wc.js 5 days ago smtp-activelayer-wc.min.js 5 days ago smtp-admin-notices.js 5 days ago smtp-admin-notices.min.js 5 days ago smtp-admin.js 5 days ago smtp-admin.min.js 5 days ago smtp-ai-mcp.js 5 days ago smtp-ai-mcp.min.js 5 days ago smtp-code-snippets.js 5 days ago smtp-code-snippets.min.js 5 days ago smtp-dashboard-widget.js 5 days ago smtp-dashboard-widget.min.js 5 days ago smtp-notifications.js 5 days ago smtp-notifications.min.js 5 days ago smtp-recommendations.js 5 days ago smtp-recommendations.min.js 5 days ago smtp-tools-debug-events.js 5 days ago smtp-tools-debug-events.min.js 5 days ago
smtp-admin.js
1397 lines
1 /* globals wp_mail_smtp, jconfirm, ajaxurl */
2 'use strict';
3
4 var WPMailSMTP = window.WPMailSMTP || {};
5 WPMailSMTP.Admin = WPMailSMTP.Admin || {};
6
7 /**
8 * WP Mail SMTP Admin area module.
9 *
10 * @since 1.6.0
11 */
12 WPMailSMTP.Admin.Settings = WPMailSMTP.Admin.Settings || ( function( document, window, $ ) {
13
14 /**
15 * Public functions and properties.
16 *
17 * @since 1.6.0
18 *
19 * @type {object}
20 */
21 var app = {
22
23 /**
24 * State attribute showing if one of the plugin settings
25 * changed and was not yet saved.
26 *
27 * @since 1.9.0
28 *
29 * @type {boolean}
30 */
31 pluginSettingsChanged: false,
32
33 /**
34 * Start the engine. DOM is not ready yet, use only to init something.
35 *
36 * @since 1.6.0
37 */
38 init: function() {
39
40 // Do that when DOM is ready.
41 $( app.ready );
42 },
43
44 /**
45 * DOM is fully loaded.
46 *
47 * @since 1.6.0
48 */
49 ready: function() {
50
51 app.pageHolder = $( '.wp-mail-smtp-tab-settings' );
52
53 app.settingsForm = $( '.wp-mail-smtp-connection-settings-form' );
54
55 // If there are screen options we have to move them.
56 $( '#screen-meta-links, #screen-meta' ).prependTo( '#wp-mail-smtp-header-temp' ).show();
57
58 app.bindActions();
59 var removableQueryParams = [ 'sendlayer_quick_connect_result', 'sendlayer_quick_connect_disconnect_result' ];
60
61 if ( ! $( '.wp-mail-smtp-tab-tools-debug-events' ).length ) {
62 removableQueryParams.push( 'debug_event_id' );
63 }
64
65 app.cleanQueryParams( removableQueryParams );
66
67 app.setJQueryConfirmDefaults();
68
69 // Flyout Menu.
70 app.initFlyoutMenu();
71 },
72
73 /**
74 * Process all generic actions/events, mostly custom that were fired by our API.
75 *
76 * @since 1.6.0
77 */
78 bindActions: function() {
79
80 // Mailer selection.
81 $( '.wp-mail-smtp-mailer-image', app.settingsForm ).on( 'click', function() {
82 $( this ).parents( '.wp-mail-smtp-mailer' ).find( 'input' ).trigger( 'click' );
83 } );
84
85 $( '.wp-mail-smtp-mailer input', app.settingsForm ).on( 'click', function() {
86 var $input = $( this );
87
88 if ( $input.prop( 'disabled' ) ) {
89
90 // Educational Popup.
91 if ( $input.hasClass( 'educate' ) ) {
92 app.education.upgradeMailer( $input );
93 }
94
95 return false;
96 }
97
98 // Deselect the current mailer.
99 $( '.wp-mail-smtp-mailer', app.settingsForm ).removeClass( 'active' );
100
101 // Select the correct one.
102 $( this ).parents( '.wp-mail-smtp-mailer' ).addClass( 'active' );
103
104 // Hide all mailers options and display for a currently clicked one.
105 $( '.wp-mail-smtp-mailer-option', app.settingsForm ).addClass( 'hidden' ).removeClass( 'active' );
106 $( '.wp-mail-smtp-mailer-option-' + $( this ).val(), app.settingsForm ).addClass( 'active' ).removeClass( 'hidden' );
107 } );
108
109 app.mailers.sendlayer.bindActions();
110 app.mailers.smtp.bindActions();
111
112 // Dismiss Pro banner at the bottom of the page.
113 $( '#wp-mail-smtp-pro-banner-dismiss', app.pageHolder ).on( 'click', function() {
114 $.ajax( {
115 url: ajaxurl,
116 dataType: 'json',
117 type: 'POST',
118 data: {
119 action: 'wp_mail_smtp_ajax',
120 task: 'pro_banner_dismiss',
121 nonce: wp_mail_smtp.nonce
122 }
123 } )
124 .always( function() {
125 $( '#wp-mail-smtp-pro-banner', app.pageHolder ).fadeOut( 'fast' );
126 } );
127 } );
128
129 // Dissmis educational notices for certain mailers.
130 $( '.js-wp-mail-smtp-mailer-notice-dismiss', app.settingsForm ).on( 'click', function( e ) {
131 e.preventDefault();
132
133 var $btn = $( this ),
134 $notice = $btn.parents( '.inline-notice' );
135
136 if ( $btn.hasClass( 'disabled' ) ) {
137 return false;
138 }
139
140 $.ajax( {
141 url: ajaxurl,
142 dataType: 'json',
143 type: 'POST',
144 data: {
145 action: 'wp_mail_smtp_ajax',
146 nonce: wp_mail_smtp.nonce,
147 task: 'notice_dismiss',
148 notice: $notice.data( 'notice' ),
149 mailer: $notice.data( 'mailer' )
150 },
151 beforeSend: function() {
152 $btn.addClass( 'disabled' );
153 }
154 } )
155 .always( function() {
156 $notice.fadeOut( 'fast', function() {
157 $btn.removeClass( 'disabled' );
158 } );
159 } );
160 } );
161
162 // Show/hide debug output.
163 $( '#wp-mail-smtp-debug .error-log-toggle' ).on( 'click', function( e ) {
164 e.preventDefault();
165
166 $( '#wp-mail-smtp-debug .error-log' ).slideToggle();
167 } );
168
169 // Copy debug output to clipboard.
170 $( '#wp-mail-smtp-debug .error-log-copy' ).on( 'click', function( e ) {
171 e.preventDefault();
172
173 var $self = $( this );
174
175 // Get error log.
176 var $content = $( '#wp-mail-smtp-debug .error-log' );
177
178 // Copy to clipboard.
179 if ( ! $content.is( ':visible' ) ) {
180 $content.addClass( 'error-log-selection' );
181 }
182 var range = document.createRange();
183 range.selectNode( $content[0] );
184 window.getSelection().removeAllRanges();
185 window.getSelection().addRange( range );
186 document.execCommand( 'Copy' );
187 window.getSelection().removeAllRanges();
188 $content.removeClass( 'error-log-selection' );
189
190 $self.addClass( 'error-log-copy-copied' );
191
192 setTimeout(
193 function() {
194 $self.removeClass( 'error-log-copy-copied' );
195 },
196 1500
197 );
198 } );
199
200 // Remove mailer connection.
201 $( '.js-wp-mail-smtp-provider-remove', app.settingsForm ).on( 'click', function() {
202 return confirm( wp_mail_smtp.text_provider_remove );
203 } );
204
205 // Copy input text to clipboard.
206 $( '.wp-mail-smtp-setting-copy', app.settingsForm ).on( 'click', function( e ) {
207 e.preventDefault();
208
209 var target = $( '#' + $( this ).data( 'source_id' ) ).get( 0 );
210
211 target.select();
212 document.execCommand( 'Copy' );
213
214 var $buttonIcon = $( this ).find( '.dashicons' );
215
216 $buttonIcon
217 .removeClass( 'dashicons-admin-page' )
218 .addClass( 'wp-mail-smtp-dashicons-yes-alt-green wp-mail-smtp-success wp-mail-smtp-animate' );
219
220 setTimeout(
221 function() {
222 $buttonIcon
223 .removeClass( 'wp-mail-smtp-dashicons-yes-alt-green wp-mail-smtp-success wp-mail-smtp-animate' )
224 .addClass( 'dashicons-admin-page' );
225 },
226 1000
227 );
228 } );
229
230 // Notice bar: click on the dissmiss button.
231 $( '#wp-mail-smtp-notice-bar' ).on( 'click', '.dismiss', function() {
232 var $notice = $( this ).closest( '#wp-mail-smtp-notice-bar' );
233
234 $notice.addClass( 'out' );
235 setTimeout(
236 function() {
237 $notice.remove();
238 },
239 300
240 );
241
242 $.post(
243 ajaxurl,
244 {
245 action: 'wp_mail_smtp_notice_bar_dismiss',
246 nonce: wp_mail_smtp.nonce,
247 }
248 );
249 } );
250
251 app.triggerExitNotice();
252 app.beforeSaveChecks();
253
254 // Register change event to show/hide plugin supported settings for currently selected mailer.
255 $( '.js-wp-mail-smtp-setting-mailer-radio-input', app.settingsForm ).on( 'change', this.processMailerSettingsOnChange );
256
257 // Disable multiple click on the Email Test tab submit button and display a loader icon.
258 $( '.wp-mail-smtp-tab-tools-test #email-test-form' ).on( 'submit', function() {
259 var $button = $( this ).find( '.wp-mail-smtp-btn' );
260
261 $button.attr( 'disabled', true );
262 $button.find( 'span' ).hide();
263 $button.find( '.wp-mail-smtp-loading' ).show();
264 } );
265
266 $( '#wp-mail-smtp-setting-gmail-one_click_setup_enabled-lite' ).on( 'click', function( e ) {
267 e.preventDefault();
268
269 app.education.gmailOneClickSetupUpgrade();
270 } );
271
272 $( '#wp-mail-smtp-setting-misc-rate_limit-lite' ).on( 'click', function( e ) {
273 e.preventDefault();
274
275 app.education.rateLimitUpgrade();
276 } );
277
278 // Confirm before enabling the "Hide Email Delivery Errors" option.
279 $( '#wp-mail-smtp-setting-email_delivery_errors_hidden' ).on( 'change', app.confirmHideDeliveryErrors );
280
281 // Obfuscated fields
282 $( '.wp-mail-smtp-btn[data-clear-field]' ).on( 'click', function( e ) {
283 var $button = $( this );
284 var fieldId = $button.attr( 'data-clear-field' );
285 var $field = $( `#${fieldId}` );
286
287 $field.prop( 'disabled', false );
288 $field.attr( 'name', $field.attr( 'data-name' ) );
289 $field.removeAttr( 'value' );
290 $field.focus();
291 $button.remove();
292 } );
293
294 $( '.email_test_tab_removal_notice' ).on( 'click', '.notice-dismiss', function() {
295 var $button = $( this );
296
297 $.ajax( {
298 url: ajaxurl,
299 dataType: 'json',
300 type: 'POST',
301 data: {
302 action: 'wp_mail_smtp_ajax',
303 nonce: wp_mail_smtp.nonce,
304 task: 'email_test_tab_removal_notice_dismiss',
305 },
306 beforeSend: function() {
307 $button.prop( 'disabled', true );
308 },
309 } );
310 } );
311
312 // Banner: toggle the inline error-log panel.
313 $( document ).on(
314 'click',
315 '.wpms-email-sending-errors-banner__error-log-toggle',
316 function( e ) {
317 e.preventDefault();
318
319 var $btn = $( this );
320 var $panel = $btn.closest( '.wpms-email-sending-errors-banner' )
321 .find( '.wpms-email-sending-errors-banner__error-log' );
322
323 if ( ! $panel.length ) {
324 return;
325 }
326
327 var showLabel = $btn.data( 'show-label' );
328 var hideLabel = $btn.data( 'hide-label' );
329 var isHidden = $panel.prop( 'hidden' ) || ! $panel.is( ':visible' );
330
331 if ( isHidden ) {
332 $panel.prop( 'hidden', false ).hide().slideDown( 200 );
333 $btn.text( hideLabel );
334 } else {
335 $panel.slideUp( 200, function() {
336 $panel.prop( 'hidden', true );
337 } );
338 $btn.text( showLabel );
339 }
340 }
341 );
342
343 // Banner: copy the inline error-log panel contents to clipboard.
344 $( document ).on(
345 'click',
346 '.wpms-email-sending-errors-error-log__copy-icon',
347 function( e ) {
348 e.preventDefault();
349
350 var $btn = $( this );
351 var $panel = $btn.closest( '.wpms-email-sending-errors-banner__error-log' );
352 var $default = $btn.find( '.wpms-email-sending-errors-error-log__copy-icon-default' );
353 var $done = $btn.find( '.wpms-email-sending-errors-error-log__copy-icon-done' );
354 var $tooltip = $panel.find( '.wpms-email-sending-errors-error-log__copy-tooltip' );
355
356 if ( ! $panel.length ) {
357 return;
358 }
359
360 var $content = $panel.clone();
361 $content.find( '.wpms-email-sending-errors-error-log__copy-icon, .wpms-email-sending-errors-error-log__copy-tooltip' ).remove();
362 $content.find( 'br' ).replaceWith( '\n' );
363 var text = $content.text().trim();
364
365 var afterCopy = function() {
366 $default.prop( 'hidden', true );
367 $done.prop( 'hidden', false );
368 $tooltip.prop( 'hidden', false );
369
370 setTimeout(
371 function() {
372 $default.prop( 'hidden', false );
373 $done.prop( 'hidden', true );
374 $tooltip.prop( 'hidden', true );
375 },
376 2000
377 );
378 };
379
380 var copyViaExecCommand = function() {
381 var $tmp = $( '<textarea>' )
382 .val( text )
383 .css( { position: 'fixed', left: '-9999px', top: 0 } )
384 .appendTo( 'body' );
385 $tmp[ 0 ].select();
386 try {
387 document.execCommand( 'copy' );
388 } catch ( err ) {
389
390 // Best-effort fallback; failure leaves the clipboard untouched.
391 }
392 $tmp.remove();
393 };
394
395 if ( navigator.clipboard && navigator.clipboard.writeText ) {
396 navigator.clipboard.writeText( text ).then( afterCopy, function() {
397 copyViaExecCommand();
398 afterCopy();
399 } );
400 } else {
401 copyViaExecCommand();
402 afterCopy();
403 }
404 }
405 );
406
407 // Dismiss email-sending-errors banner.
408 $( document ).on(
409 'click',
410 '.wpms-email-sending-errors-banner__dismiss',
411 function( e ) {
412 e.preventDefault();
413
414 var $el = $( this ).closest( '[data-connection-id]' );
415 var connectionId = $el.data( 'connection-id' );
416
417 if ( ! connectionId ) {
418 return;
419 }
420
421 $.post( wp_mail_smtp.ajax_url, {
422 action: 'wp_mail_smtp_email_sending_errors_dismiss',
423 nonce: wp_mail_smtp.nonce,
424 connection_id: connectionId
425 } ).done( function( res ) {
426 if ( res && res.success ) {
427 $el.slideUp( 200, function() {
428 $el.remove();
429 } );
430 return;
431 }
432 app.pluginInstall.showErrorModal( app.extractAjaxError( res, wp_mail_smtp.dismiss_error ) );
433 } ).fail( function( xhr ) {
434 var res = xhr && xhr.responseJSON ? xhr.responseJSON : null;
435 app.pluginInstall.showErrorModal( app.extractAjaxError( res, wp_mail_smtp.dismiss_error ) );
436 } );
437 }
438 );
439
440 // Dismiss one-liner: WP's is-dismissible handles slideUp; we fire the AJAX clear.
441 $( document ).on(
442 'click',
443 '.wpms-email-sending-errors-one-liner .notice-dismiss',
444 function() {
445 var $el = $( this ).closest( '[data-connection-id]' );
446 var connectionId = $el.data( 'connection-id' );
447
448 if ( ! connectionId ) {
449 return;
450 }
451
452 $.post( wp_mail_smtp.ajax_url, {
453 action: 'wp_mail_smtp_email_sending_errors_dismiss',
454 nonce: wp_mail_smtp.nonce,
455 connection_id: connectionId
456 } ).done( function( res ) {
457 if ( res && res.success ) {
458 return;
459 }
460 app.pluginInstall.showErrorModal( app.extractAjaxError( res, wp_mail_smtp.dismiss_error ) );
461 } ).fail( function( xhr ) {
462 var res = xhr && xhr.responseJSON ? xhr.responseJSON : null;
463 app.pluginInstall.showErrorModal( app.extractAjaxError( res, wp_mail_smtp.dismiss_error ) );
464 } );
465 }
466 );
467
468 // Per-session dismiss for the test-success banner. DOM removal
469 // only, no AJAX; banner is regenerated on each successful test send.
470 $( document ).on(
471 'click',
472 '.wpms-test-email-success-banner__dismiss',
473 function( e ) {
474 e.preventDefault();
475
476 $( this ).closest( '.wpms-test-email-success-banner' ).slideUp( 200, function() {
477 $( this ).remove();
478 } );
479 }
480 );
481
482 // Generic plugin install/activate for any opt-in button. Mirrors
483 // the About Us page's AJAX flow but works on any markup that
484 // carries .js-wp-mail-smtp-plugin-install-btn + status-* class +
485 // data-plugin (zip URL initially, swapped to basename after
486 // install so a follow-up activate click reuses the same attribute).
487 $( document ).on( 'click', '.js-wp-mail-smtp-plugin-install-btn', app.handlePluginInstallBtnClick );
488
489 // Text-link variant of the install/activate flow used by the Pro Tip
490 // strip. Same backend as the button handler; different DOM mutations
491 // (inline loader + full strip-content swap on success).
492 $( document ).on( 'click', '.js-wp-mail-smtp-plugin-install-link', app.handlePluginInstallLinkClick );
493 },
494
495 /**
496 * Handle a click on a generic plugin install/activate button.
497 *
498 * @since 4.9.0
499 *
500 * @param {object} e jQuery click event.
501 */
502 handlePluginInstallBtnClick: function( e ) {
503
504 e.preventDefault();
505
506 var $btn = $( this );
507
508 // After install+activate the same button doubles as a Setup Now CTA:
509 // clicking navigates to the plugin's settings page (status-active +
510 // data-settings-url). Keeps a single element and one event hook.
511 if ( $btn.hasClass( 'status-active' ) ) {
512 var settingsUrl = $btn.attr( 'data-settings-url' );
513
514 if ( settingsUrl ) {
515 window.location.href = settingsUrl;
516 }
517
518 return;
519 }
520
521 if ( $btn.hasClass( 'wp-mail-smtp-btn-loading' ) || $btn.prop( 'disabled' ) ) {
522 return;
523 }
524
525 var task;
526 if ( $btn.hasClass( 'status-download' ) ) {
527 task = 'about_plugin_install';
528 } else if ( $btn.hasClass( 'status-inactive' ) ) {
529 task = 'about_plugin_activate';
530 } else {
531 return;
532 }
533
534 var originalLabel = $btn.html();
535 var strings = wp_mail_smtp.plugin_install;
536
537 $btn.addClass( 'wp-mail-smtp-btn-loading' );
538 $btn.prop( 'disabled', true );
539 $btn.text( strings.processing );
540
541 app.pluginInstall.installPlugin( {
542 plugin: $btn.attr( 'data-plugin' ),
543 task: task,
544 onSuccess: function( res ) {
545
546 if ( task === 'about_plugin_install' && res.data && res.data.basename ) {
547 $btn.attr( 'data-plugin', res.data.basename );
548 }
549
550 // Flash a transient confirmation beside the button (About Us
551 // pattern). Backend returns a localized msg for both
552 // install-only and install+activate outcomes. .html()
553 // (matches About Us) so HTML entities from esc_html__ —
554 // `&amp;` for the `&` in "installed & activated" — decode
555 // instead of rendering as literal `&amp;`.
556 if ( res.data && res.data.msg ) {
557 var $actions = $btn.closest( '.wpms-test-email-success-banner__card-actions' );
558 var $msg = $( '<p class="wpms-test-email-success-banner__card-msg" />' ).html( res.data.msg );
559
560 $actions.find( '.wpms-test-email-success-banner__card-msg' ).remove();
561 $actions.append( $msg );
562
563 setTimeout( function() {
564 $msg.fadeOut( 200, function() {
565 $( this ).remove();
566 } );
567 }, 3000 );
568 }
569
570 // Install succeeded but silent activation failed (host may
571 // allow install_plugins without activate_plugins).
572 if ( task === 'about_plugin_install' && res.data && res.data.is_activated === false ) {
573 $btn
574 .removeClass( 'wp-mail-smtp-btn-loading status-download' )
575 .addClass( 'status-inactive' )
576 .prop( 'disabled', false )
577 .text( strings.activate );
578
579 return;
580 }
581
582 // Activate task lands here too — install-with-activation and
583 // standalone activate transition the same way: the button
584 // becomes a Setup Now CTA. status-active here means
585 // "installed + click navigates to settings" — the click
586 // handler reads data-settings-url and changes location.
587 var settingsUrl = $btn.attr( 'data-settings-url' );
588
589 $btn
590 .removeClass( 'wp-mail-smtp-btn-loading status-download status-inactive' )
591 .addClass( 'status-active' );
592
593 if ( settingsUrl ) {
594 $btn
595 .prop( 'disabled', false )
596 .text( strings.setup_now );
597
598 return;
599 }
600
601 // Fallback: catalog entry without a settings page URL — leave
602 // the button in a disabled "Installed" state.
603 $btn
604 .prop( 'disabled', true )
605 .text( strings.installed );
606 },
607 onError: function( message ) {
608 $btn.removeClass( 'wp-mail-smtp-btn-loading' );
609 $btn.prop( 'disabled', false );
610 $btn.html( originalLabel );
611 app.pluginInstall.showErrorModal( message );
612 },
613 } );
614 },
615
616 /**
617 * Handle a click on a Pro-Tip-strip install/activate text-link. Same
618 * backend as the button handler; different DOM mutations — inline
619 * loader beside the link during install, and on success the initial
620 * strip content is swapped for the pre-rendered success span.
621 *
622 * @since 4.9.0
623 *
624 * @param {object} e jQuery click event.
625 */
626 handlePluginInstallLinkClick: function( e ) {
627
628 e.preventDefault();
629
630 var $link = $( this );
631
632 if ( $link.hasClass( 'wp-mail-smtp-link-loading' ) || $link.hasClass( 'status-active' ) ) {
633 return;
634 }
635
636 var task;
637 if ( $link.hasClass( 'status-download' ) ) {
638 task = 'about_plugin_install';
639 } else if ( $link.hasClass( 'status-inactive' ) ) {
640 task = 'about_plugin_activate';
641 } else {
642 return;
643 }
644
645 var $strip = $link.closest( '.wpms-test-email-pro-tip-strip' );
646 var originalLabel = $link.html();
647 var strings = wp_mail_smtp.plugin_install;
648 var $loader = $( '<span class="wpms-test-email-pro-tip-strip__loader wp-mail-smtp-loading-spin wp-mail-smtp-loading-sm" aria-hidden="true"></span>' );
649
650 $link.addClass( 'wp-mail-smtp-link-loading' );
651 $link.css( 'pointer-events', 'none' );
652 $link.after( $loader );
653
654 app.pluginInstall.installPlugin( {
655 plugin: $link.attr( 'data-plugin' ),
656 task: task,
657 onSuccess: function( res ) {
658
659 if ( task === 'about_plugin_install' && res.data && res.data.basename ) {
660 $link.attr( 'data-plugin', res.data.basename );
661 }
662
663 // Install succeeded but activation didn't — transition the
664 // link to status-inactive so the user can retry activate.
665 if ( task === 'about_plugin_install' && res.data && res.data.is_activated === false ) {
666 $loader.remove();
667
668 var activateLabel = strings.activate_with_name.replace( '%s', $link.data( 'plugin-name' ) || '' );
669
670 $link
671 .removeClass( 'wp-mail-smtp-link-loading status-download' )
672 .addClass( 'status-inactive' )
673 .css( 'pointer-events', '' )
674 .text( activateLabel );
675
676 return;
677 }
678
679 // Activate task lands here too — caller's onSuccess treats
680 // install-with-activation and standalone activate the same:
681 // hide the initial span, reveal the pre-rendered success span.
682 $loader.remove();
683 $link.removeClass( 'wp-mail-smtp-link-loading' );
684 $link.css( 'pointer-events', '' );
685
686 $strip.find( '.wpms-test-email-pro-tip-strip__initial' ).attr( 'hidden', true );
687 $strip.find( '.wpms-test-email-pro-tip-strip__success' ).removeAttr( 'hidden' );
688 },
689 onError: function( message ) {
690 $loader.remove();
691 $link.removeClass( 'wp-mail-smtp-link-loading' );
692 $link.css( 'pointer-events', '' );
693 $link.html( originalLabel );
694 app.pluginInstall.showErrorModal( message );
695 },
696 } );
697 },
698
699 education: {
700 upgradeMailer: function( $input ) {
701
702 var mailerName = $input.data( 'title' ).trim();
703
704 app.education.upgradeModal(
705 wp_mail_smtp.education.upgrade_title.replace( /%name%/g, mailerName ),
706 wp_mail_smtp.education.upgrade_content.replace( /%name%/g, mailerName ),
707 $input.val()
708 );
709 },
710
711 gmailOneClickSetupUpgrade: function() {
712
713 app.education.upgradeModal(
714 wp_mail_smtp.education.gmail.one_click_setup_upgrade_title,
715 wp_mail_smtp.education.gmail.one_click_setup_upgrade_content,
716 'gmail-one-click-setup'
717 );
718 },
719
720 rateLimitUpgrade: function() {
721
722 app.education.upgradeModal(
723 wp_mail_smtp.education.rate_limit.upgrade_title,
724 wp_mail_smtp.education.rate_limit.upgrade_content,
725 'rate-limit-setting'
726 );
727 },
728
729 upgradeModal: function( title, content, upgradeUrlUtmContent ) {
730
731 $.alert( {
732 backgroundDismiss: true,
733 escapeKey: true,
734 animationBounce: 1,
735 type: 'blue',
736 closeIcon: true,
737 title: title,
738 icon: '"></i>' + wp_mail_smtp.education.upgrade_icon_lock + '<i class="',
739 content: content,
740 boxWidth: '550px',
741 onOpenBefore: function() {
742 this.$btnc.after( '<div class="discount-note">' + wp_mail_smtp.education.upgrade_bonus + wp_mail_smtp.education.upgrade_doc + '</div>' );
743 this.$body.addClass( 'wp-mail-smtp-upgrade-mailer-education-modal' );
744 },
745 buttons: {
746 confirm: {
747 text: wp_mail_smtp.education.upgrade_button,
748 btnClass: 'btn-confirm',
749 keys: [ 'enter' ],
750 action: function() {
751 var appendChar = /(\?)/.test( wp_mail_smtp.education.upgrade_url ) ? '&' : '?',
752 upgradeURL = wp_mail_smtp.education.upgrade_url + appendChar + 'utm_content=' + encodeURIComponent( upgradeUrlUtmContent );
753
754 window.open( upgradeURL, '_blank' );
755 }
756 }
757 }
758 } );
759 }
760 },
761
762 /**
763 * Individual mailers specific js code.
764 *
765 * @since 1.6.0
766 */
767 mailers: {
768 sendlayer: {
769
770 /**
771 * Show a SendLayer connect error modal with message and optional error code.
772 *
773 * @since 4.8.0
774 *
775 * @param {string} message The error message to display.
776 * @param {string} errorCode The dot-notation error code (optional).
777 */
778 showConnectError: function( message, errorCode ) {
779
780 var content = '<p>' + $( '<span>' ).text( message ).html() + '</p>';
781
782 if ( errorCode ) {
783 content += '<div class="wp-mail-smtp-error-code-box">' +
784 '<code>' + $( '<span>' ).text( errorCode ).html() + '</code>' +
785 '<button type="button" class="wp-mail-smtp-error-code-box__copy" title="Copy">' +
786 '<svg class="wp-mail-smtp-error-code-box__icon-copy" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg>' +
787 '<svg class="wp-mail-smtp-error-code-box__icon-check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="display:none;"><path fill="#0f8a56" d="M256 512c141.4 0 256-114.6 256-256S397.4 0 256 0S0 114.6 0 256S114.6 512 256 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"/></svg>' +
788 '</button>' +
789 '</div>';
790 }
791
792 $.alert( {
793 backgroundDismiss: true,
794 escapeKey: true,
795 animationBounce: 1,
796 type: 'red',
797 closeIcon: true,
798 icon: app.getModalIcon( 'times-circle-red' ),
799 title: wp_mail_smtp.sendlayer.error_title,
800 content: content,
801 boxWidth: '450px',
802 buttons: {
803 confirm: {
804 text: wp_mail_smtp.ok_text,
805 btnClass: 'wp-mail-smtp-btn wp-mail-smtp-btn-md',
806 keys: [ 'enter' ]
807 }
808 },
809 onOpenBefore: function() {
810 this.$body.on( 'click', '.wp-mail-smtp-error-code-box__copy', function() {
811 var $btn = $( this );
812 var code = $btn.siblings( 'code' ).text();
813
814 if ( navigator.clipboard ) {
815 navigator.clipboard.writeText( code );
816 }
817
818 $btn.find( '.wp-mail-smtp-error-code-box__icon-copy' ).hide();
819 $btn.find( '.wp-mail-smtp-error-code-box__icon-check' ).show();
820
821 setTimeout( function() {
822 $btn.find( '.wp-mail-smtp-error-code-box__icon-check' ).hide();
823 $btn.find( '.wp-mail-smtp-error-code-box__icon-copy' ).show();
824 }, 2000 );
825 } );
826 }
827 } );
828 },
829
830 /**
831 * Start the connect flow via AJAX and handle errors with the modal.
832 *
833 * @since 4.8.0
834 *
835 * @param {object} connectArgs Extra arguments to pass to the connect endpoint (e.g. { utm_content: '...' }).
836 * @param {Function} onDone Callback when the request completes (success or error).
837 */
838 doConnect: function( connectArgs, onDone ) {
839
840 var self = this;
841 var returnUrl = $( '#wp-mail-smtp-sendlayer-quick-connect-return-url' ).val() || wp_mail_smtp.sendlayer.return_url;
842 var connectionId = $( '#wp-mail-smtp-sendlayer-quick-connect-connection-id' ).val() || '';
843
844 $.post( ajaxurl, { // eslint-disable-line camelcase
845 action: 'wp_mail_smtp_sendlayer_connect',
846 nonce: wp_mail_smtp.sendlayer.connect_nonce,
847 return_url: returnUrl, // eslint-disable-line camelcase
848 connection_id: connectionId, // eslint-disable-line camelcase
849 connect_args: connectArgs || {}, // eslint-disable-line camelcase
850 }, function( response ) { // eslint-disable-line complexity
851 if ( response.success && response.data.redirect_url ) {
852 window.location.href = response.data.redirect_url;
853 } else {
854 var message = response.data && response.data.message ? response.data.message : wp_mail_smtp.sendlayer.error_text;
855 var errorCode = response.data && response.data.error_code ? response.data.error_code : '';
856 self.showConnectError( message, errorCode );
857 if ( onDone ) {
858 onDone();
859 }
860 }
861 } ).fail( function() {
862 self.showConnectError( wp_mail_smtp.sendlayer.server_error, 'plugin.init_connect.ajax_failed' );
863 if ( onDone ) {
864 onDone();
865 }
866 } );
867 },
868
869 /**
870 * Bind SendLayer-specific UI actions.
871 *
872 * @since 4.8.0
873 */
874 bindActions: function() {
875
876 var self = this;
877
878 // Quick Connect button.
879 $( '#wp-mail-smtp-sendlayer-connect-btn' ).on( 'click', function( e ) {
880 e.preventDefault();
881
882 var $btn = $( this );
883 $btn.addClass( 'wp-mail-smtp-btn-loading' );
884
885 self.doConnect( { utm_content: 'Plugin Settings - Quick Connect' }, function() { // eslint-disable-line camelcase
886 $btn.removeClass( 'wp-mail-smtp-btn-loading' );
887 } );
888 } );
889
890 // Change domain link (same flow as Quick Connect).
891 $( '#wp-mail-smtp-sendlayer-change-domain' ).on( 'click', function( e ) {
892 e.preventDefault();
893
894 var $link = $( this );
895 var originalText = $link.text();
896 $link.text( wp_mail_smtp.sendlayer.connecting_text );
897
898 self.doConnect( { utm_content: 'Plugin Settings - Quick Connect Change Domain' }, function() { // eslint-disable-line camelcase
899 $link.text( originalText );
900 } );
901 } );
902
903 // Show Quick Connect when API key is removed.
904 $( '.wp-mail-smtp-btn[data-clear-field="wp-mail-smtp-setting-sendlayer-api_key"]' ).on( 'click', function() {
905 $( '#wp-mail-smtp-setting-row-sendlayer-connect' ).show();
906 } );
907
908 // Show API key field and remove the toggle link.
909 $( '#wp-mail-smtp-sendlayer-show-api-key' ).on( 'click', function( e ) {
910 e.preventDefault();
911 $( this ).closest( '.wp-mail-smtp-setting-row' ).remove();
912 $( '#wp-mail-smtp-setting-row-sendlayer-api_key' ).show();
913 } );
914
915 // SendLayer education banner: Setup button (same flow as Quick Connect).
916 $( '#wp-mail-smtp-sendlayer-education-connect-btn' ).on( 'click', function( e ) {
917 e.preventDefault();
918
919 var $btn = $( this );
920 $btn.addClass( 'wp-mail-smtp-btn-loading' );
921
922 self.doConnect( { utm_content: 'Plugin Settings - Quick Connect Education' }, function() { // eslint-disable-line camelcase
923 $btn.removeClass( 'wp-mail-smtp-btn-loading' );
924 } );
925 } );
926
927 // SendLayer Quick Connect button — supports per-button data-mode
928 // (e.g. backup-mailer mode from the test email success banner).
929 $( document ).on( 'click', '.js-wp-mail-smtp-sendlayer-quick-connect-btn', function( e ) {
930 e.preventDefault();
931
932 var $btn = $( this );
933
934 if ( $btn.hasClass( 'wp-mail-smtp-btn-loading' ) ) {
935 return;
936 }
937
938 $btn.addClass( 'wp-mail-smtp-btn-loading' );
939
940 var connectArgs = {
941 utm_content: $btn.data( 'utm-content' ), // eslint-disable-line camelcase
942 };
943
944 var btnMode = $btn.data( 'mode' );
945
946 if ( btnMode ) {
947 connectArgs.mode = btnMode;
948 }
949
950 self.doConnect( connectArgs, function() {
951 $btn.removeClass( 'wp-mail-smtp-btn-loading' );
952 } );
953 } );
954
955 // Inline SendLayer Quick Connect link (same flow as Quick Connect).
956 $( document ).on( 'click', '.js-wp-mail-smtp-sendlayer-quick-connect-link', function( e ) {
957 e.preventDefault();
958
959 var $link = $( this );
960
961 if ( $link.next( '.wp-mail-smtp-inline-loader' ).length ) {
962 return;
963 }
964
965 var $loader = $( '<span class="wp-mail-smtp-inline-loader" aria-hidden="true"></span>' );
966 $link.after( $loader );
967
968 self.doConnect( { utm_content: 'Email Sending Errors Banner - Quick Connect' }, function() { // eslint-disable-line camelcase
969 $loader.remove();
970 } );
971 } );
972
973 // SendLayer education banner: Dismiss.
974 $( '.js-wp-mail-smtp-sendlayer-education-dismiss' ).on( 'click', function( e ) {
975 e.preventDefault();
976
977 var $banner = $( this ).closest( '.wp-mail-smtp-sendlayer-education' );
978
979 $banner.fadeOut( 200 );
980
981 $.post( ajaxurl, {
982 action: 'wp_mail_smtp_ajax',
983 task: 'notice_dismiss',
984 notice: 'sendlayer_education',
985 nonce: wp_mail_smtp.nonce,
986 } );
987 } );
988 }
989 },
990 smtp: {
991 bindActions: function() {
992
993 // Hide SMTP-specific user/pass when Auth disabled.
994 $( '#wp-mail-smtp-setting-smtp-auth' ).on( 'change', function() {
995 $( '#wp-mail-smtp-setting-row-smtp-user, #wp-mail-smtp-setting-row-smtp-pass' ).toggleClass( 'inactive' );
996 } );
997
998 // Port default values based on encryption type.
999 $( '#wp-mail-smtp-setting-row-smtp-encryption input' ).on( 'change', function() {
1000
1001 var $input = $( this ),
1002 $smtpPort = $( '#wp-mail-smtp-setting-smtp-port', app.settingsForm );
1003
1004 if ( 'tls' === $input.val() ) {
1005 $smtpPort.val( '587' );
1006 $( '#wp-mail-smtp-setting-row-smtp-autotls' ).addClass( 'inactive' );
1007 } else if ( 'ssl' === $input.val() ) {
1008 $smtpPort.val( '465' );
1009 $( '#wp-mail-smtp-setting-row-smtp-autotls' ).removeClass( 'inactive' );
1010 } else {
1011 $smtpPort.val( '25' );
1012 $( '#wp-mail-smtp-setting-row-smtp-autotls' ).removeClass( 'inactive' );
1013 }
1014 } );
1015 }
1016 }
1017 },
1018
1019 /**
1020 * Plugin install/activate utilities. Shared by the tile-button and
1021 * Pro-Tip-strip handlers; the handlers own DOM mutation, these
1022 * helpers only normalize the AJAX roundtrip and error UI.
1023 *
1024 * @since 4.9.0
1025 */
1026 pluginInstall: {
1027
1028 /**
1029 * POST to the shared About-tab plugin install/activate AJAX
1030 * endpoint and dispatch to caller-supplied success/error
1031 * callbacks.
1032 *
1033 * @since 4.9.0
1034 *
1035 * @param {object} options Options.
1036 * @param {string} options.plugin data-plugin value to send.
1037 * @param {string} options.task 'about_plugin_install' or 'about_plugin_activate'.
1038 * @param {Function} options.onSuccess Receives the parsed response.
1039 * @param {Function} options.onError Receives (message, rawResponse|null).
1040 */
1041 installPlugin: function( options ) {
1042
1043 $.post( wp_mail_smtp.ajax_url, {
1044 action: 'wp_mail_smtp_ajax',
1045 task: options.task,
1046 nonce: wp_mail_smtp.nonce,
1047 plugin: options.plugin,
1048 } ).done( function( res ) {
1049 if ( res && res.success ) {
1050 options.onSuccess( res );
1051 return;
1052 }
1053 options.onError( app.extractAjaxError( res, wp_mail_smtp.plugin_install.error ), res );
1054 } ).fail( function( xhr ) {
1055 var res = xhr && xhr.responseJSON ? xhr.responseJSON : null;
1056 options.onError( app.extractAjaxError( res, wp_mail_smtp.plugin_install.error ), res );
1057 } );
1058 },
1059
1060 /**
1061 * Show a jconfirm error modal for a plugin install/activate
1062 * failure.
1063 *
1064 * @since 4.9.0
1065 *
1066 * @param {string} message The localized error message body.
1067 */
1068 showErrorModal: function( message ) {
1069
1070 var strings = wp_mail_smtp.plugin_install;
1071
1072 $.confirm( {
1073 backgroundDismiss: false,
1074 escapeKey: true,
1075 animationBounce: 1,
1076 closeIcon: true,
1077 type: 'red',
1078 title: strings.error_title,
1079 content: message,
1080 buttons: {
1081 confirm: {
1082 text: strings.btn_ok,
1083 btnClass: 'btn-confirm',
1084 keys: [ 'enter' ],
1085 },
1086 },
1087 } );
1088 },
1089 },
1090
1091 /**
1092 * Extract a user-facing message from a wp_send_json_error() response.
1093 *
1094 * Covers the standard shape `{ success: false, data: 'message' }`
1095 * (plain string from `wp_send_json_error( $message )`). Empty or
1096 * non-string payloads (network failures, WP_Error arrays whose codes
1097 * are usually cryptic) fall back to the caller-supplied default.
1098 *
1099 * @since 4.9.0
1100 *
1101 * @param {object|null} response Parsed AJAX response, or null on network failure.
1102 * @param {string} defaultMessage Fallback when the response has no usable message.
1103 *
1104 * @returns {string} The extracted message, or the default when none is usable.
1105 */
1106 extractAjaxError: function( response, defaultMessage ) {
1107
1108 if ( response && typeof response.data === 'string' && response.data.length ) {
1109 return response.data;
1110 }
1111
1112 return defaultMessage;
1113 },
1114
1115 /**
1116 * Returns prepared modal icon HTML for a jQuery Confirm dialog.
1117 *
1118 * @since 4.9.0
1119 *
1120 * @param {string} icon The icon name from /assets/images/font-awesome/ to use in the modal.
1121 *
1122 * @returns {string} Modal icon HTML.
1123 */
1124 getModalIcon: function( icon ) {
1125
1126 return '"></i><img src="' + wp_mail_smtp.plugin_url + '/assets/images/font-awesome/' + icon + '.svg" style="width: 40px; height: 40px;" alt=""><i class="';
1127 },
1128
1129 /**
1130 * Confirm before enabling the "Hide Email Delivery Errors" option.
1131 *
1132 * Enabling this suppresses the warnings that surface failed email
1133 * delivery, so it requires explicit confirmation. Cancelling reverts
1134 * the toggle to its previous (unchecked) state. Turning the option
1135 * off is never prompted.
1136 *
1137 * @since 4.9.0
1138 *
1139 * @param {Event} e The change event.
1140 */
1141 confirmHideDeliveryErrors: function( e ) {
1142
1143 var $toggle = $( e.target );
1144
1145 // Only confirm when the option is being enabled.
1146 if ( ! $toggle.prop( 'checked' ) ) {
1147 return;
1148 }
1149
1150 var strings = wp_mail_smtp.hide_delivery_errors;
1151
1152 $.confirm( {
1153 backgroundDismiss: false,
1154 escapeKey: true,
1155 animationBounce: 1,
1156 type: 'orange',
1157 icon: app.getModalIcon( 'exclamation-circle-solid-orange' ),
1158 title: strings.title,
1159 content: strings.content,
1160 boxWidth: '550px',
1161 buttons: {
1162 confirm: {
1163 text: strings.confirm_button,
1164 btnClass: 'btn-confirm',
1165 keys: [ 'enter' ],
1166 },
1167 cancel: {
1168 text: strings.cancel_button,
1169 btnClass: 'btn-cancel',
1170 action: function() {
1171 $toggle.prop( 'checked', false );
1172 },
1173 },
1174 },
1175 } );
1176 },
1177
1178 /**
1179 * Exit notice JS code when plugin settings are not saved.
1180 *
1181 * @since 1.9.0
1182 */
1183 triggerExitNotice: function() {
1184
1185 var $settingPages = $( '.wp-mail-smtp-page-general' );
1186
1187 // Display an exit notice, if settings are not saved.
1188 $( window ).on( 'beforeunload', function() {
1189 if ( app.pluginSettingsChanged ) {
1190 return wp_mail_smtp.text_settings_not_saved;
1191 }
1192 } );
1193
1194 // Set settings changed attribute, if any input was changed.
1195 $( ':input:not( #wp-mail-smtp-setting-license-key, .wp-mail-smtp-not-form-input, #wp-mail-smtp-setting-gmail-one_click_setup_enabled, #wp-mail-smtp-setting-outlook-one_click_setup_enabled )', $settingPages ).on( 'change', function() {
1196 app.pluginSettingsChanged = true;
1197 } );
1198
1199 // Clear the settings changed attribute, if the settings are about to be saved.
1200 $( 'form', $settingPages ).on( 'submit', function() {
1201 app.pluginSettingsChanged = false;
1202 } );
1203 },
1204
1205 /**
1206 * Perform any checks before the settings are saved.
1207 *
1208 * Checks:
1209 * - warn users if they try to save the settings with the default (PHP) mailer selected.
1210 *
1211 * @since 2.1.0
1212 */
1213 beforeSaveChecks: function() {
1214
1215 app.settingsForm.on( 'submit', function() {
1216 if ( $( '.wp-mail-smtp-mailer input:checked', app.settingsForm ).val() === 'mail' ) {
1217 var $thisForm = $( this );
1218
1219 $.alert( {
1220 backgroundDismiss: false,
1221 escapeKey: false,
1222 animationBounce: 1,
1223 type: 'orange',
1224 icon: '"></i><img src="' + wp_mail_smtp.plugin_url + '/assets/images/font-awesome/exclamation-circle-solid-orange.svg" style="width: 40px; height: 40px;" alt="' + wp_mail_smtp.default_mailer_notice.icon_alt + '"><i class="',
1225 title: wp_mail_smtp.default_mailer_notice.title,
1226 content: wp_mail_smtp.default_mailer_notice.content,
1227 boxWidth: '550px',
1228 buttons: {
1229 confirm: {
1230 text: wp_mail_smtp.default_mailer_notice.save_button,
1231 btnClass: 'btn-confirm',
1232 keys: [ 'enter' ],
1233 action: function() {
1234 $thisForm.off( 'submit' ).trigger( 'submit' );
1235 }
1236 },
1237 cancel: {
1238 text: wp_mail_smtp.default_mailer_notice.cancel_button,
1239 btnClass: 'btn-cancel',
1240 },
1241 }
1242 } );
1243
1244 return false;
1245 }
1246 } );
1247 },
1248
1249 /**
1250 * On change callback for showing/hiding plugin supported settings for currently selected mailer.
1251 *
1252 * @since 2.3.0
1253 */
1254 processMailerSettingsOnChange: function() {
1255
1256 var selectedMailer = $( this ).val();
1257 var mailerSupportedSettings = wp_mail_smtp.all_mailers_supports[ selectedMailer ];
1258
1259 for ( var setting in mailerSupportedSettings ) {
1260 // eslint-disable-next-line no-prototype-builtins
1261 if ( mailerSupportedSettings.hasOwnProperty( setting ) ) {
1262 $( '.js-wp-mail-smtp-setting-' + setting, app.settingsForm ).toggle( mailerSupportedSettings[ setting ] );
1263 }
1264 }
1265
1266 // Special case: "from email" (group settings).
1267 var $mainSettingInGroup = $( '.js-wp-mail-smtp-setting-from_email' );
1268 var $quickConnectFromEmail = $( '#wp-mail-smtp-setting-row-sendlayer-quick-connect-from_email' );
1269 var isQuickConnectActive = selectedMailer === 'sendlayer' && $quickConnectFromEmail.length > 0;
1270
1271 $mainSettingInGroup.toggle(
1272 ! isQuickConnectActive && ( mailerSupportedSettings[ 'from_email' ] || mailerSupportedSettings[ 'from_email_force' ] )
1273 );
1274
1275 // Toggle quick connect From Email field and disable inputs when hidden
1276 // to prevent split fields from being submitted for other mailers.
1277 $quickConnectFromEmail.toggle( isQuickConnectActive );
1278 $quickConnectFromEmail.find( 'input' ).prop( 'disabled', ! isQuickConnectActive );
1279
1280 // Special case: "from name" (group settings).
1281 $mainSettingInGroup = $( '.js-wp-mail-smtp-setting-from_name' );
1282
1283 $mainSettingInGroup.toggle(
1284 mailerSupportedSettings['from_name'] || mailerSupportedSettings['from_name_force']
1285 );
1286 },
1287
1288 /**
1289 * Remove transient query params from the URL without a page reload.
1290 *
1291 * Useful for cleaning up one-time result params after they have been
1292 * read and rendered on the current page load.
1293 *
1294 * @since 4.8.0
1295 *
1296 * @param {string[]} params List of query parameter names to remove.
1297 */
1298 cleanQueryParams: function( params ) {
1299
1300 try {
1301 var url = new URL( window.location.href );
1302 var dirty = false;
1303
1304 params.forEach( function( param ) {
1305 if ( url.searchParams.has( param ) ) {
1306 url.searchParams.delete( param );
1307 dirty = true;
1308 }
1309 } );
1310
1311 if ( dirty ) {
1312 window.history.replaceState( {}, document.title, url.toString() );
1313 }
1314 } catch ( e ) {} // eslint-disable-line no-empty
1315 },
1316
1317 /**
1318 * Set jQuery-Confirm default options.
1319 *
1320 * @since 2.9.0
1321 */
1322 setJQueryConfirmDefaults: function() {
1323
1324 jconfirm.defaults = {
1325 typeAnimated: false,
1326 draggable: false,
1327 animateFromElement: false,
1328 theme: 'modern',
1329 boxWidth: '400px',
1330 useBootstrap: false
1331 };
1332 },
1333
1334 /**
1335 * Flyout Menu (quick links).
1336 *
1337 * @since 3.0.0
1338 */
1339 initFlyoutMenu: function() {
1340
1341 // Flyout Menu Elements.
1342 var $flyoutMenu = $( '#wp-mail-smtp-flyout' );
1343
1344 if ( $flyoutMenu.length === 0 ) {
1345 return;
1346 }
1347
1348 var $head = $flyoutMenu.find( '.wp-mail-smtp-flyout-head' );
1349
1350 // Click on the menu head icon.
1351 $head.on( 'click', function( e ) {
1352 e.preventDefault();
1353 $flyoutMenu.toggleClass( 'opened' );
1354 } );
1355
1356 // Page elements and other values.
1357 var $wpfooter = $( '#wpfooter' );
1358
1359 if ( $wpfooter.length === 0 ) {
1360 return;
1361 }
1362
1363 var $overlap = $(
1364 '.wp-mail-smtp-page-logs-archive, ' +
1365 '.wp-mail-smtp-tab-tools-action-scheduler, ' +
1366 '.wp-mail-smtp-page-reports, ' +
1367 '.wp-mail-smtp-tab-tools-debug-events, ' +
1368 '.wp-mail-smtp-tab-connections'
1369 );
1370
1371 // Hide menu if scrolled down to the bottom of the page or overlap some critical controls.
1372 $( window ).on( 'resize scroll', _.debounce( function() {
1373
1374 var wpfooterTop = $wpfooter.offset().top,
1375 wpfooterBottom = wpfooterTop + $wpfooter.height(),
1376 overlapBottom = $overlap.length > 0 ? $overlap.offset().top + $overlap.height() + 85 : 0,
1377 viewTop = $( window ).scrollTop(),
1378 viewBottom = viewTop + $( window ).height();
1379
1380 if ( wpfooterBottom <= viewBottom && wpfooterTop >= viewTop && overlapBottom > viewBottom ) {
1381 $flyoutMenu.addClass( 'out' );
1382 } else {
1383 $flyoutMenu.removeClass( 'out' );
1384 }
1385 }, 50 ) );
1386
1387 $( window ).trigger( 'scroll' );
1388 }
1389 };
1390
1391 // Provide access to public functions/properties.
1392 return app;
1393 }( document, window, jQuery ) );
1394
1395 // Initialize.
1396 WPMailSMTP.Admin.Settings.init();
1397