PageSourceSearch

https://theeasymaster.com/wp-content/themes/easymaster-theme-main/assets/newsletter.js?ver=1790783952

js theeasymaster.com collected 2026-10-02 01:45:57 UTC 4,618 bytes, 160 lines download raw bytes

1/**
2 * Newsletter forms.
3 *
4 * Binds by class rather than by a list of IDs, so a form added anywhere works
5 * without anyone remembering to come back here -- which is how the sidebar
6 * widget ended up submitting as a plain POST and reloading the page.
7 *
8 * Every outcome is said out loud: the old handler wrote a message on success
9 * and, on failure, un-hid an empty paragraph, so a mistyped address produced
10 * a blank space and no reason.
11 */
12( function () {
13	'use strict';
14
15	function config() {
16		var data = window.EasyMasterData || {};
17
18		return {
19			ajaxUrl: data.ajaxUrl || '',
20			nonce: data.nonce || ''
21		};
22	}
23
24	function setUp( form ) {
25		var message = form.querySelector( '.em-newsletter-msg' );
26		var input = form.querySelector( 'input[name="email"]' );
27		var button = form.querySelector( 'button[type="submit"]' );
28		var trap = form.querySelector( 'input[name="em_website"]' );
29		var fields = form.querySelector( '.em-newsletter-fields' );
30		var source = form.querySelector( 'input[name="source"]' );
31		var busy = false;
32
33		if ( ! message || ! input ) {
34			return;
35		}
36
37		var label = button ? button.textContent : '';
38
39		function say( text, kind ) {
40			var failed = kind === 'error';
41
42			message.textContent = text;
43			message.hidden = false;
44			message.classList.remove( 'is-error', 'is-success' );
45			message.classList.add( failed ? 'is-error' : 'is-success' );
46
47			// On success the form has done its job, so the confirmation takes
48			// the field's place rather than hanging below it -- nothing moves,
49			// and nothing is left sitting there inviting a second go. A
50			// refusal keeps the field: it is what has to be corrected.
51			if ( fields ) {
52				fields.hidden = ! failed;
53			}
54		}
55
56		function setBusy( state ) {
57			busy = state;
58			form.classList.toggle( 'is-busy', state );
59
60			if ( button ) {
61				button.disabled = state;
62				button.textContent = state ? 'Subscribing…' : label;
63			}
64		}
65
66		form.addEventListener( 'submit', function ( event ) {
67			event.preventDefault();
68
69			if ( busy ) {
70				return;
71			}
72
73			var email = input.value.trim();
74			var settings = config();
75
76			if ( ! email ) {
77				say( 'Enter your email address first.', 'error' );
78				input.focus();
79				return;
80			}
81
82			// The browser's own check, before spending a request on it.
83			if ( input.checkValidity && ! input.checkValidity() ) {
84				say( 'That does not look like an email address.', 'error' );
85				input.focus();
86				return;
87			}
88
89			if ( ! settings.ajaxUrl ) {
90				say( 'The form is not available right now. Please try again later.', 'error' );
91				return;
92			}
93
94			var body = new URLSearchParams();
95			body.append( 'action', 'em_newsletter_subscribe' );
96			body.append( 'nonce', settings.nonce );
97			body.append( 'email', email );
98			body.append( 'em_website', trap ? trap.value : '' );
99			body.append( 'source', source ? source.value : '' );
100
101			setBusy( true );
102
103			fetch( settings.ajaxUrl, {
104				method: 'POST',
105				credentials: 'same-origin',
106				headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
107				body: body.toString()
108			} )
109				.then( function ( response ) {
110					// A rejection is still JSON; a nonce failure is the bare
111					// string "-1", which JSON.parse would throw on.
112					return response.text().then( function ( text ) {
113						try {
114							return { status: response.status, payload: JSON.parse( text ) };
115						} catch ( e ) {
116							return { status: response.status, payload: null };
117						}
118					} );
119				} )
120				.then( function ( result ) {
121					var payload = result.payload;
122
123					if ( payload && payload.success ) {
124						say( ( payload.data && payload.data.message ) || 'Subscribed!', 'success' );
125						input.value = '';
126						return;
127					}
128
129					if ( payload && payload.data && payload.data.message ) {
130						say( payload.data.message, 'error' );
131						return;
132					}
133
134					say( 'That did not go through. Please reload the page and try again.', 'error' );
135				} )
136				.catch( function () {
137					say( 'Could not reach the server. Check your connection and try again.', 'error' );
138				} )
139				.then( function () {
140					setBusy( false );
141				} );
142		} );
143
144		// Clear a refusal as soon as the reader starts fixing it.
145		input.addEventListener( 'input', function () {
146			if ( message.classList.contains( 'is-error' ) ) {
147				message.hidden = true;
148				message.textContent = '';
149				message.classList.remove( 'is-error' );
150			}
151		} );
152
153		// Nothing to clear on success: the field is gone by then.
154		
155	}
156
157	document.addEventListener( 'DOMContentLoaded', function () {
158		Array.prototype.forEach.call( document.querySelectorAll( '.em-newsletter-form' ), setUp );
159	} );
160}() );

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.