| 1 |
/** |
| 2 |
* NotificationX Elementor Form — submission handler. |
| 3 |
* |
| 4 |
* Intercepts the form submit, posts Name / Email / Message to the |
| 5 |
* notificationx/v1/popup-submit REST endpoint and shows a success or |
| 6 |
* error message. The selected NX campaign ID is read from data-nx-id. |
| 7 |
*/ |
| 8 |
( function () { |
| 9 |
'use strict'; |
| 10 |
|
| 11 |
function init( form ) { |
| 12 |
if ( ! form || form.__nxBound ) return; |
| 13 |
form.__nxBound = true; |
| 14 |
|
| 15 |
var msgEl = form.querySelector( '.nx-form-message' ); |
| 16 |
var btn = form.querySelector( '.nx-form-submit' ); |
| 17 |
|
| 18 |
form.addEventListener( 'submit', function ( ev ) { |
| 19 |
ev.preventDefault(); |
| 20 |
|
| 21 |
if ( msgEl ) { |
| 22 |
msgEl.textContent = ''; |
| 23 |
msgEl.classList.remove( 'is-success', 'is-error' ); |
| 24 |
} |
| 25 |
|
| 26 |
// Native required-field validation. |
| 27 |
if ( typeof form.checkValidity === 'function' && ! form.checkValidity() ) { |
| 28 |
form.reportValidity(); |
| 29 |
return; |
| 30 |
} |
| 31 |
|
| 32 |
var nxId = form.getAttribute( 'data-nx-id' ); |
| 33 |
var url = form.getAttribute( 'data-rest-url' ); |
| 34 |
if ( ! nxId || ! url ) return; |
| 35 |
|
| 36 |
var payload = { |
| 37 |
nx_id: nxId, |
| 38 |
timestamp: Math.floor( Date.now() / 1000 ), |
| 39 |
}; |
| 40 |
|
| 41 |
var nameEl = form.querySelector( '[name="name"]' ); |
| 42 |
var emailEl = form.querySelector( '[name="email"]' ); |
| 43 |
var messageEl = form.querySelector( '[name="message"]' ); |
| 44 |
|
| 45 |
if ( nameEl ) payload.name = nameEl.value; |
| 46 |
if ( emailEl ) payload.email = emailEl.value; |
| 47 |
if ( messageEl ) payload.message = messageEl.value; |
| 48 |
|
| 49 |
if ( btn ) btn.disabled = true; |
| 50 |
|
| 51 |
// popup-submit is a public endpoint (permission_callback => __return_true) |
| 52 |
// and never verifies a nonce server-side. We deliberately do NOT send an |
| 53 |
// X-WP-Nonce header: a baked-in wp_rest nonce goes stale in the Elementor |
| 54 |
// builder and on cached pages, and WordPress core would then reject the |
| 55 |
// request with "Cookie check failed" (rest_cookie_invalid_nonce). With no |
| 56 |
// nonce, core treats the submission as anonymous and lets it through. |
| 57 |
var headers = { 'Content-Type': 'application/json' }; |
| 58 |
|
| 59 |
fetch( url, { |
| 60 |
method: 'POST', |
| 61 |
headers: headers, |
| 62 |
body: JSON.stringify( payload ), |
| 63 |
} ) |
| 64 |
.then( function ( res ) { |
| 65 |
return res.json().then( function ( body ) { |
| 66 |
return { ok: res.ok && body && body.success, body: body }; |
| 67 |
} ).catch( function () { |
| 68 |
return { ok: res.ok, body: {} }; |
| 69 |
} ); |
| 70 |
} ) |
| 71 |
.then( function ( result ) { |
| 72 |
if ( ! msgEl ) return; |
| 73 |
if ( result.ok ) { |
| 74 |
msgEl.classList.add( 'is-success' ); |
| 75 |
msgEl.textContent = form.getAttribute( 'data-success' ) || 'Submitted.'; |
| 76 |
form.reset(); |
| 77 |
} else { |
| 78 |
msgEl.classList.add( 'is-error' ); |
| 79 |
msgEl.textContent = ( result.body && result.body.message ) |
| 80 |
|| form.getAttribute( 'data-error' ) |
| 81 |
|| 'Something went wrong.'; |
| 82 |
} |
| 83 |
} ) |
| 84 |
.catch( function () { |
| 85 |
if ( ! msgEl ) return; |
| 86 |
msgEl.classList.add( 'is-error' ); |
| 87 |
msgEl.textContent = form.getAttribute( 'data-error' ) || 'Something went wrong.'; |
| 88 |
} ) |
| 89 |
.finally( function () { |
| 90 |
if ( btn ) btn.disabled = false; |
| 91 |
} ); |
| 92 |
} ); |
| 93 |
} |
| 94 |
|
| 95 |
function bindAll( root ) { |
| 96 |
( root || document ).querySelectorAll( '.nx-form' ).forEach( init ); |
| 97 |
} |
| 98 |
|
| 99 |
if ( document.readyState === 'loading' ) { |
| 100 |
document.addEventListener( 'DOMContentLoaded', function () { bindAll(); } ); |
| 101 |
} else { |
| 102 |
bindAll(); |
| 103 |
} |
| 104 |
|
| 105 |
// Re-bind in the Elementor editor preview when widgets re-render. |
| 106 |
if ( window.jQuery ) { |
| 107 |
window.jQuery( window ).on( 'elementor/frontend/init', function () { |
| 108 |
if ( window.elementorFrontend && window.elementorFrontend.hooks ) { |
| 109 |
window.elementorFrontend.hooks.addAction( |
| 110 |
'frontend/element_ready/nx-form.default', |
| 111 |
function ( $scope ) { bindAll( $scope[ 0 ] ); } |
| 112 |
); |
| 113 |
} |
| 114 |
} ); |
| 115 |
} |
| 116 |
} )(); |
| 117 |
|