PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / trunk
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar vtrunk
3.3.1 3.3.0 3.2.14 3.2.13 3.2.12 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 trunk 0.2.5.5 0.2.5.6 0.2.5.7 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 All 156 releases
notificationx / includes / Extensions / Elementor / FormWidget.php

FormWidget.php in NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar trunk, at includes/Extensions/Elementor/FormWidget.php

686 lines 29.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * NotificationX Elementor Form Widget
4 *
5 * A simple Name / Email / Message form whose submissions are saved into
6 * the NotificationX `nx_entries` table via the existing
7 * `notificationx/v1/popup-submit` REST endpoint. The widget must be bound
8 * to an existing NotificationX campaign of source `popup_notification`
9 * or `exit_intent_custom`.
10 *
11 * @package NotificationX\Extensions\Elementor
12 */
13
14 namespace NotificationX\Extensions\Elementor;
15
16 use Elementor\Controls_Manager;
17 use Elementor\Group_Control_Border;
18 use Elementor\Group_Control_Box_Shadow;
19 use Elementor\Group_Control_Typography;
20 use Elementor\Widget_Base;
21 use NotificationX\Core\PostType;
22
23 if ( ! defined( 'ABSPATH' ) ) {
24 exit;
25 }
26
27 /**
28 * Column-width options shared across all field controls.
29 * Keys are the CSS percentage values rendered into `flex-basis`.
30 */
31 if ( ! function_exists( __NAMESPACE__ . '\\nx_form_widths' ) ) {
32 function nx_form_widths() {
33 return [
34 '100' => '100%',
35 '75' => '75%',
36 '66' => '66%',
37 '50' => '50%',
38 '33' => '33%',
39 '25' => '25%',
40 ];
41 }
42 }
43
44 class FormWidget extends Widget_Base {
45
46 public function get_name() {
47 return 'nx-form';
48 }
49
50 public function get_title() {
51 return esc_html__( 'NotificationX Form', 'notificationx' );
52 }
53
54 public function get_icon() {
55 return 'eicon-form-horizontal';
56 }
57
58 public function get_categories() {
59 return [ 'notificationx' ];
60 }
61
62 public function get_keywords() {
63 return [ 'form', 'contact', 'lead', 'notificationx', 'nx', 'entries', 'subscribe' ];
64 }
65
66 public function get_script_depends() {
67 return [ 'nx-elementor-form' ];
68 }
69
70 public function get_style_depends() {
71 return [ 'nx-elementor-form' ];
72 }
73
74 /**
75 * Existing NX Popup / Exit-Intent campaigns to bind submissions to.
76 *
77 * @return array<int|string,string>
78 */
79 private function get_nx_campaigns() {
80 $options = [ '' => esc_html__( '— Select a Campaign —', 'notificationx' ) ];
81
82 if ( ! class_exists( PostType::class ) ) {
83 return $options;
84 }
85
86 $posts = PostType::get_instance()->get_posts(
87 [], // can't AND two source values via a simple where; filter below.
88 'nx_id, title, source'
89 );
90
91 if ( is_array( $posts ) ) {
92 foreach ( $posts as $post ) {
93 if ( empty( $post['source'] ) ) {
94 continue;
95 }
96 if ( ! in_array( $post['source'], [ 'popup_notification', 'exit_intent_custom' ], true ) ) {
97 continue;
98 }
99 /* translators: %d: notification ID */
100 $label = $post['title'] ?: sprintf( __( '#%d', 'notificationx' ), $post['nx_id'] );
101 $options[ (string) $post['nx_id'] ] = sprintf(
102 '%s (%s)',
103 $label,
104 $post['source'] === 'exit_intent_custom' ? __( 'Exit Intent', 'notificationx' ) : __( 'Popup', 'notificationx' )
105 );
106 }
107 }
108
109 return $options;
110 }
111
112 /**
113 * Whether NotificationX Pro is active. Pro unlocks the Email field and the
114 * per-field Column Width controls; the free version forces a single-column
115 * (100%) layout and does not collect email.
116 *
117 * @return bool
118 */
119 private function is_pro() {
120 return class_exists( '\\NotificationXPro\\NotificationX' );
121 }
122
123 protected function register_controls() {
124
125 $is_pro = $this->is_pro();
126
127 // ── Form Settings ─────────────────────────────────────────────────
128 $this->start_controls_section(
129 'section_form_settings',
130 [ 'label' => esc_html__( 'Form Settings', 'notificationx' ) ]
131 );
132
133 $this->add_control(
134 'nx_campaign_id',
135 [
136 'label' => esc_html__( 'Select Notification ID', 'notificationx' ),
137 'type' => Controls_Manager::SELECT,
138 'options' => $this->get_nx_campaigns(),
139 'default' => '',
140 'description' => esc_html__( 'Submissions are saved as entries against the selected Popup or Exit-Intent campaign.', 'notificationx' ),
141 ]
142 );
143
144 $this->add_control(
145 'nx_form_title',
146 [
147 'label' => esc_html__( 'Form Title', 'notificationx' ),
148 'type' => Controls_Manager::TEXT,
149 'default' => esc_html__( 'Get in touch', 'notificationx' ),
150 'dynamic' => [ 'active' => true ],
151 ]
152 );
153
154 // Name field
155 $this->add_control(
156 'nx_name_heading',
157 [ 'label' => esc_html__( 'Name Field', 'notificationx' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before' ]
158 );
159
160 if ( $is_pro ) {
161 $this->add_control(
162 'nx_show_name',
163 [ 'label' => esc_html__( 'Show Name', 'notificationx' ), 'type' => Controls_Manager::SWITCHER, 'return_value' => 'yes', 'default' => 'yes' ]
164 );
165 $this->add_responsive_control(
166 'nx_name_width',
167 [
168 'label' => esc_html__( 'Column Width', 'notificationx' ),
169 'type' => Controls_Manager::SELECT,
170 'options' => nx_form_widths(),
171 'default' => '100',
172 'condition' => [ 'nx_show_name' => 'yes' ],
173 ]
174 );
175 $this->add_control(
176 'nx_name_label',
177 [ 'label' => esc_html__( 'Label', 'notificationx' ), 'type' => Controls_Manager::TEXT, 'default' => esc_html__( 'Name', 'notificationx' ), 'condition' => [ 'nx_show_name' => 'yes' ] ]
178 );
179 $this->add_control(
180 'nx_name_placeholder',
181 [ 'label' => esc_html__( 'Placeholder', 'notificationx' ), 'type' => Controls_Manager::TEXT, 'default' => esc_html__( 'Your name', 'notificationx' ), 'condition' => [ 'nx_show_name' => 'yes' ] ]
182 );
183 $this->add_control(
184 'nx_name_required',
185 [ 'label' => esc_html__( 'Required', 'notificationx' ), 'type' => Controls_Manager::SWITCHER, 'return_value' => 'yes', 'default' => '', 'condition' => [ 'nx_show_name' => 'yes' ] ]
186 );
187 } else {
188 // Free version: the Name field is a Pro-only feature. Show a notice
189 // instead of the controls so the field can't be enabled.
190 $this->add_control(
191 'nx_name_pro_notice',
192 [
193 'type' => Controls_Manager::RAW_HTML,
194 'raw' => esc_html__( 'The Name field is available in NotificationX Pro.', 'notificationx' ),
195 'content_classes' => 'elementor-panel-alert elementor-panel-alert-info',
196 ]
197 );
198 }
199
200 // Email field
201 $this->add_control(
202 'nx_email_heading',
203 [ 'label' => esc_html__( 'Email Field', 'notificationx' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before' ]
204 );
205
206 if ( $is_pro ) {
207 $this->add_control(
208 'nx_show_email',
209 [ 'label' => esc_html__( 'Show Email', 'notificationx' ), 'type' => Controls_Manager::SWITCHER, 'return_value' => 'yes', 'default' => 'yes' ]
210 );
211 $this->add_responsive_control(
212 'nx_email_width',
213 [
214 'label' => esc_html__( 'Column Width', 'notificationx' ),
215 'type' => Controls_Manager::SELECT,
216 'options' => nx_form_widths(),
217 'default' => '100',
218 'condition' => [ 'nx_show_email' => 'yes' ],
219 ]
220 );
221 $this->add_control(
222 'nx_email_label',
223 [ 'label' => esc_html__( 'Label', 'notificationx' ), 'type' => Controls_Manager::TEXT, 'default' => esc_html__( 'Email', 'notificationx' ), 'condition' => [ 'nx_show_email' => 'yes' ] ]
224 );
225 $this->add_control(
226 'nx_email_placeholder',
227 [ 'label' => esc_html__( 'Placeholder', 'notificationx' ), 'type' => Controls_Manager::TEXT, 'default' => esc_html__( 'you@example.com', 'notificationx' ), 'condition' => [ 'nx_show_email' => 'yes' ] ]
228 );
229 $this->add_control(
230 'nx_email_required',
231 [ 'label' => esc_html__( 'Required', 'notificationx' ), 'type' => Controls_Manager::SWITCHER, 'return_value' => 'yes', 'default' => 'yes', 'condition' => [ 'nx_show_email' => 'yes' ] ]
232 );
233 } else {
234 // Free version: the Email field is a Pro-only feature. Show a notice
235 // instead of the controls so the field can't be enabled.
236 $this->add_control(
237 'nx_email_pro_notice',
238 [
239 'type' => Controls_Manager::RAW_HTML,
240 'raw' => esc_html__( 'The Email field is available in NotificationX Pro.', 'notificationx' ),
241 'content_classes' => 'elementor-panel-alert elementor-panel-alert-info',
242 ]
243 );
244 }
245
246 // Message field
247 $this->add_control(
248 'nx_message_heading',
249 [ 'label' => esc_html__( 'Message Field', 'notificationx' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before' ]
250 );
251 $this->add_control(
252 'nx_show_message',
253 [ 'label' => esc_html__( 'Show Message', 'notificationx' ), 'type' => Controls_Manager::SWITCHER, 'return_value' => 'yes', 'default' => 'yes' ]
254 );
255 $this->add_responsive_control(
256 'nx_message_width',
257 [
258 'label' => esc_html__( 'Column Width', 'notificationx' ),
259 'type' => Controls_Manager::SELECT,
260 'options' => nx_form_widths(),
261 'default' => '100',
262 'condition' => [ 'nx_show_message' => 'yes' ],
263 ]
264 );
265 $this->add_control(
266 'nx_message_label',
267 [ 'label' => esc_html__( 'Label', 'notificationx' ), 'type' => Controls_Manager::TEXT, 'default' => esc_html__( 'Message', 'notificationx' ), 'condition' => [ 'nx_show_message' => 'yes' ] ]
268 );
269 $this->add_control(
270 'nx_message_placeholder',
271 [ 'label' => esc_html__( 'Placeholder', 'notificationx' ), 'type' => Controls_Manager::TEXT, 'default' => esc_html__( 'Write your message…', 'notificationx' ), 'condition' => [ 'nx_show_message' => 'yes' ] ]
272 );
273 $this->add_control(
274 'nx_message_rows',
275 [ 'label' => esc_html__( 'Rows', 'notificationx' ), 'type' => Controls_Manager::NUMBER, 'default' => 3, 'min' => 1, 'max' => 20, 'condition' => [ 'nx_show_message' => 'yes' ] ]
276 );
277 $this->add_control(
278 'nx_message_required',
279 [ 'label' => esc_html__( 'Required', 'notificationx' ), 'type' => Controls_Manager::SWITCHER, 'return_value' => 'yes', 'default' => '', 'condition' => [ 'nx_show_message' => 'yes' ] ]
280 );
281
282 // Submit
283 $this->add_control(
284 'nx_submit_heading',
285 [ 'label' => esc_html__( 'Submit', 'notificationx' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before' ]
286 );
287 $this->add_responsive_control(
288 'nx_submit_width',
289 [
290 'label' => esc_html__( 'Column Width', 'notificationx' ),
291 'type' => Controls_Manager::SELECT,
292 'options' => nx_form_widths(),
293 'default' => '100',
294 ]
295 );
296 $this->add_control(
297 'nx_submit_text',
298 [ 'label' => esc_html__( 'Button Text', 'notificationx' ), 'type' => Controls_Manager::TEXT, 'default' => esc_html__( 'Submit', 'notificationx' ) ]
299 );
300 $this->add_control(
301 'nx_success_message',
302 [ 'label' => esc_html__( 'Success Message', 'notificationx' ), 'type' => Controls_Manager::TEXTAREA, 'default' => esc_html__( 'Thanks! Your submission has been received.', 'notificationx' ) ]
303 );
304 $this->add_control(
305 'nx_error_message',
306 [ 'label' => esc_html__( 'Error Message', 'notificationx' ), 'type' => Controls_Manager::TEXTAREA, 'default' => esc_html__( 'Something went wrong. Please try again.', 'notificationx' ) ]
307 );
308
309 $this->end_controls_section();
310
311 // ── Style: Form ──────────────────────────────────────────────────
312 $this->start_controls_section(
313 'section_style_form',
314 [ 'label' => esc_html__( 'Form', 'notificationx' ), 'tab' => Controls_Manager::TAB_STYLE ]
315 );
316
317 $this->add_responsive_control(
318 'nx_form_align',
319 [
320 'label' => esc_html__( 'Alignment', 'notificationx' ),
321 'type' => Controls_Manager::CHOOSE,
322 'options' => [
323 'left' => [ 'title' => esc_html__( 'Left', 'notificationx' ), 'icon' => 'eicon-text-align-left' ],
324 'center' => [ 'title' => esc_html__( 'Center', 'notificationx' ), 'icon' => 'eicon-text-align-center' ],
325 'right' => [ 'title' => esc_html__( 'Right', 'notificationx' ), 'icon' => 'eicon-text-align-right' ],
326 ],
327 'default' => 'left',
328 'selectors' => [ '{{WRAPPER}} .nx-form-title' => 'text-align: {{VALUE}};' ],
329 ]
330 );
331
332 $this->add_group_control(
333 Group_Control_Typography::get_type(),
334 [ 'name' => 'nx_title_typography', 'selector' => '{{WRAPPER}} .nx-form-title' ]
335 );
336
337 $this->add_control(
338 'nx_title_color',
339 [
340 'label' => esc_html__( 'Title Color', 'notificationx' ),
341 'type' => Controls_Manager::COLOR,
342 'selectors' => [ '{{WRAPPER}} .nx-form-title' => 'color: {{VALUE}};' ],
343 ]
344 );
345
346 $this->end_controls_section();
347
348 // ── Style: Fields ────────────────────────────────────────────────
349 $this->start_controls_section(
350 'section_style_fields',
351 [ 'label' => esc_html__( 'Fields', 'notificationx' ), 'tab' => Controls_Manager::TAB_STYLE ]
352 );
353
354 $this->add_control(
355 'nx_label_color',
356 [
357 'label' => esc_html__( 'Label Color', 'notificationx' ),
358 'type' => Controls_Manager::COLOR,
359 'selectors' => [ '{{WRAPPER}} .nx-form-label' => 'color: {{VALUE}};' ],
360 ]
361 );
362
363 $this->add_group_control(
364 Group_Control_Typography::get_type(),
365 [ 'name' => 'nx_label_typography', 'selector' => '{{WRAPPER}} .nx-form-label' ]
366 );
367
368 $this->add_control(
369 'nx_input_text_color',
370 [
371 'label' => esc_html__( 'Input Text Color', 'notificationx' ),
372 'type' => Controls_Manager::COLOR,
373 'selectors' => [ '{{WRAPPER}} .nx-form-input' => 'color: {{VALUE}};' ],
374 ]
375 );
376
377 $this->add_control(
378 'nx_input_bg_color',
379 [
380 'label' => esc_html__( 'Input Background', 'notificationx' ),
381 'type' => Controls_Manager::COLOR,
382 'selectors' => [ '{{WRAPPER}} .nx-form-input' => 'background-color: {{VALUE}};' ],
383 ]
384 );
385
386 $this->add_control(
387 'nx_placeholder_color',
388 [
389 'label' => esc_html__( 'Placeholder Color', 'notificationx' ),
390 'type' => Controls_Manager::COLOR,
391 'selectors' => [
392 '{{WRAPPER}} .nx-form-input::-webkit-input-placeholder' => 'color: {{VALUE}};',
393 '{{WRAPPER}} .nx-form-input::-moz-placeholder' => 'color: {{VALUE}};',
394 '{{WRAPPER}} .nx-form-input:-ms-input-placeholder' => 'color: {{VALUE}};',
395 '{{WRAPPER}} .nx-form-input::placeholder' => 'color: {{VALUE}};',
396 ],
397 ]
398 );
399
400 $this->add_group_control(
401 Group_Control_Typography::get_type(),
402 [
403 'name' => 'nx_placeholder_typography',
404 'label' => esc_html__( 'Placeholder Typography', 'notificationx' ),
405 'selector' => '{{WRAPPER}} .nx-form-input::placeholder',
406 ]
407 );
408
409 $this->add_group_control(
410 Group_Control_Border::get_type(),
411 [
412 'name' => 'nx_input_border',
413 'selector' => '{{WRAPPER}} .nx-form-input',
414 ]
415 );
416
417 $this->add_control(
418 'nx_input_radius',
419 [
420 'label' => esc_html__( 'Border Radius', 'notificationx' ),
421 'type' => Controls_Manager::DIMENSIONS,
422 'size_units' => [ 'px', '%' ],
423 'selectors' => [ '{{WRAPPER}} .nx-form-input' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ],
424 ]
425 );
426
427 $this->add_control(
428 'nx_input_padding',
429 [
430 'label' => esc_html__( 'Padding', 'notificationx' ),
431 'type' => Controls_Manager::DIMENSIONS,
432 'size_units' => [ 'px', 'em' ],
433 'selectors' => [ '{{WRAPPER}} .nx-form-input' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ],
434 ]
435 );
436
437 $this->add_control(
438 'nx_field_spacing',
439 [
440 'label' => esc_html__( 'Row Gap (Vertical)', 'notificationx' ),
441 'type' => Controls_Manager::SLIDER,
442 'size_units' => [ 'px' ],
443 'range' => [ 'px' => [ 'min' => 0, 'max' => 60 ] ],
444 'default' => [ 'unit' => 'px', 'size' => 14 ],
445 'selectors' => [ '{{WRAPPER}} .nx-form-rows' => 'row-gap: {{SIZE}}{{UNIT}};' ],
446 ]
447 );
448
449 $this->add_control(
450 'nx_column_gap',
451 [
452 'label' => esc_html__( 'Column Gap (Horizontal)', 'notificationx' ),
453 'type' => Controls_Manager::SLIDER,
454 'size_units' => [ 'px' ],
455 'range' => [ 'px' => [ 'min' => 0, 'max' => 60 ] ],
456 'default' => [ 'unit' => 'px', 'size' => 14 ],
457 'selectors' => [ '{{WRAPPER}} .nx-form-rows' => 'column-gap: {{SIZE}}{{UNIT}}; --nx-gap: {{SIZE}}{{UNIT}};' ],
458 ]
459 );
460
461 $this->end_controls_section();
462
463 // ── Style: Button ────────────────────────────────────────────────
464 $this->start_controls_section(
465 'section_style_button',
466 [ 'label' => esc_html__( 'Button', 'notificationx' ), 'tab' => Controls_Manager::TAB_STYLE ]
467 );
468
469 $this->add_group_control(
470 Group_Control_Typography::get_type(),
471 [ 'name' => 'nx_button_typography', 'selector' => '{{WRAPPER}} .nx-form-submit' ]
472 );
473
474 $this->start_controls_tabs( 'nx_button_tabs' );
475
476 $this->start_controls_tab( 'nx_button_tab_normal', [ 'label' => esc_html__( 'Normal', 'notificationx' ) ] );
477 $this->add_control(
478 'nx_button_color',
479 [ 'label' => esc_html__( 'Text Color', 'notificationx' ), 'type' => Controls_Manager::COLOR, 'default' => '#ffffff', 'selectors' => [ '{{WRAPPER}} .nx-form-submit' => 'color: {{VALUE}};' ] ]
480 );
481 $this->add_control(
482 'nx_button_bg',
483 [ 'label' => esc_html__( 'Background', 'notificationx' ), 'type' => Controls_Manager::COLOR, 'default' => '#2271b1', 'selectors' => [ '{{WRAPPER}} .nx-form-submit' => 'background-color: {{VALUE}};' ] ]
484 );
485 $this->end_controls_tab();
486
487 $this->start_controls_tab( 'nx_button_tab_hover', [ 'label' => esc_html__( 'Hover', 'notificationx' ) ] );
488 $this->add_control(
489 'nx_button_color_h',
490 [ 'label' => esc_html__( 'Text Color', 'notificationx' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .nx-form-submit:hover' => 'color: {{VALUE}};' ] ]
491 );
492 $this->add_control(
493 'nx_button_bg_h',
494 [ 'label' => esc_html__( 'Background', 'notificationx' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .nx-form-submit:hover' => 'background-color: {{VALUE}};' ] ]
495 );
496 $this->end_controls_tab();
497
498 $this->end_controls_tabs();
499
500 $this->add_group_control(
501 Group_Control_Border::get_type(),
502 [ 'name' => 'nx_button_border', 'selector' => '{{WRAPPER}} .nx-form-submit' ]
503 );
504
505 $this->add_control(
506 'nx_button_radius',
507 [
508 'label' => esc_html__( 'Border Radius', 'notificationx' ),
509 'type' => Controls_Manager::DIMENSIONS,
510 'size_units' => [ 'px', '%' ],
511 'selectors' => [ '{{WRAPPER}} .nx-form-submit' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ],
512 ]
513 );
514
515 $this->add_control(
516 'nx_button_padding',
517 [
518 'label' => esc_html__( 'Padding', 'notificationx' ),
519 'type' => Controls_Manager::DIMENSIONS,
520 'size_units' => [ 'px', 'em' ],
521 'default' => [ 'top' => '12', 'right' => '20', 'bottom' => '12', 'left' => '20', 'unit' => 'px', 'isLinked' => false ],
522 'selectors' => [ '{{WRAPPER}} .nx-form-submit' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ],
523 ]
524 );
525
526 $this->add_responsive_control(
527 'nx_button_align',
528 [
529 'label' => esc_html__( 'Alignment', 'notificationx' ),
530 'type' => Controls_Manager::CHOOSE,
531 'options' => [
532 'flex-start' => [ 'title' => esc_html__( 'Left', 'notificationx' ), 'icon' => 'eicon-text-align-left' ],
533 'center' => [ 'title' => esc_html__( 'Center', 'notificationx' ), 'icon' => 'eicon-text-align-center' ],
534 'flex-end' => [ 'title' => esc_html__( 'Right', 'notificationx' ), 'icon' => 'eicon-text-align-right' ],
535 'stretch' => [ 'title' => esc_html__( 'Justified', 'notificationx' ), 'icon' => 'eicon-text-align-justify' ],
536 ],
537 'default' => 'stretch',
538 'selectors' => [ '{{WRAPPER}} .nx-form-actions' => 'justify-content: {{VALUE}};' ],
539 ]
540 );
541
542 $this->end_controls_section();
543 }
544
545 /**
546 * Build the class string for a row given per-breakpoint width settings.
547 *
548 * @param array $s Settings array.
549 * @param string $base_key The control base name (e.g. `nx_name_width`).
550 * @return string
551 */
552 private function row_width_classes( $s, $base_key ) {
553 $classes = [ 'nx-form-row' ];
554 $map = [
555 '' => $s[ $base_key ] ?? '100',
556 'tablet-' => $s[ $base_key . '_tablet' ] ?? '',
557 'mobile-' => $s[ $base_key . '_mobile' ] ?? '',
558 ];
559 foreach ( $map as $prefix => $val ) {
560 if ( $val !== '' && $val !== null ) {
561 $classes[] = 'nx-w-' . $prefix . $val;
562 }
563 }
564 return implode( ' ', array_map( 'sanitize_html_class', $classes ) );
565 }
566
567 protected function render() {
568 $s = $this->get_settings_for_display();
569
570 $campaign_id = absint( $s['nx_campaign_id'] ?? 0 );
571 $rest_url = esc_url_raw( rest_url( 'notificationx/v1/popup-submit' ) );
572
573 $form_id = 'nx-form-' . esc_attr( $this->get_id() );
574 $show_name = ! empty( $s['nx_show_name'] );
575 $show_email = ! empty( $s['nx_show_email'] );
576 $show_message = ! empty( $s['nx_show_message'] );
577
578 // Free version: Name and Email are Pro-only fields, so only the Message
579 // field is collected. Enforce this at render time too, so settings saved
580 // while Pro was active don't leak through after Pro is deactivated.
581 if ( ! $this->is_pro() ) {
582 $show_name = false;
583 $show_email = false;
584 }
585
586 // Don't render the form at all if no campaign is selected — show a
587 // friendly editor-only notice.
588 if ( ! $campaign_id ) {
589 if ( \Elementor\Plugin::$instance->editor->is_edit_mode() ) {
590 printf(
591 '<div class="nx-form-notice">%s</div>',
592 esc_html__( 'Select a NotificationX campaign in the Form Settings to start collecting entries.', 'notificationx' )
593 );
594 }
595 return;
596 }
597 ?>
598 <div class="nx-form-wrapper">
599
600 <?php if ( ! empty( $s['nx_form_title'] ) ) : ?>
601 <h3 class="nx-form-title"><?php echo esc_html( $s['nx_form_title'] ); ?></h3>
602 <?php endif; ?>
603
604 <form
605 id="<?php echo esc_attr( $form_id ); ?>"
606 class="nx-form"
607 data-nx-id="<?php echo esc_attr( $campaign_id ); ?>"
608 data-rest-url="<?php echo esc_attr( $rest_url ); ?>"
609 data-success="<?php echo esc_attr( $s['nx_success_message'] ?? '' ); ?>"
610 data-error="<?php echo esc_attr( $s['nx_error_message'] ?? '' ); ?>"
611 novalidate
612 >
613 <div class="nx-form-rows">
614
615 <?php if ( $show_name ) : ?>
616 <div class="<?php echo esc_attr( $this->row_width_classes( $s, 'nx_name_width' ) ); ?>">
617 <?php if ( ! empty( $s['nx_name_label'] ) ) : ?>
618 <label class="nx-form-label" for="<?php echo esc_attr( $form_id ); ?>-name">
619 <?php echo esc_html( $s['nx_name_label'] ); ?>
620 <?php if ( ! empty( $s['nx_name_required'] ) ) echo ' <span class="nx-form-required">*</span>'; ?>
621 </label>
622 <?php endif; ?>
623 <input
624 type="text"
625 id="<?php echo esc_attr( $form_id ); ?>-name"
626 name="name"
627 class="nx-form-input"
628 placeholder="<?php echo esc_attr( $s['nx_name_placeholder'] ?? '' ); ?>"
629 <?php if ( ! empty( $s['nx_name_required'] ) ) echo 'required'; ?>
630 >
631 </div>
632 <?php endif; ?>
633
634 <?php if ( $show_email ) : ?>
635 <div class="<?php echo esc_attr( $this->row_width_classes( $s, 'nx_email_width' ) ); ?>">
636 <?php if ( ! empty( $s['nx_email_label'] ) ) : ?>
637 <label class="nx-form-label" for="<?php echo esc_attr( $form_id ); ?>-email">
638 <?php echo esc_html( $s['nx_email_label'] ); ?>
639 <?php if ( ! empty( $s['nx_email_required'] ) ) echo ' <span class="nx-form-required">*</span>'; ?>
640 </label>
641 <?php endif; ?>
642 <input
643 type="email"
644 id="<?php echo esc_attr( $form_id ); ?>-email"
645 name="email"
646 class="nx-form-input"
647 placeholder="<?php echo esc_attr( $s['nx_email_placeholder'] ?? '' ); ?>"
648 <?php if ( ! empty( $s['nx_email_required'] ) ) echo 'required'; ?>
649 >
650 </div>
651 <?php endif; ?>
652
653 <?php if ( $show_message ) : ?>
654 <div class="<?php echo esc_attr( $this->row_width_classes( $s, 'nx_message_width' ) ); ?>">
655 <?php if ( ! empty( $s['nx_message_label'] ) ) : ?>
656 <label class="nx-form-label" for="<?php echo esc_attr( $form_id ); ?>-message">
657 <?php echo esc_html( $s['nx_message_label'] ); ?>
658 <?php if ( ! empty( $s['nx_message_required'] ) ) echo ' <span class="nx-form-required">*</span>'; ?>
659 </label>
660 <?php endif; ?>
661 <textarea
662 id="<?php echo esc_attr( $form_id ); ?>-message"
663 name="message"
664 class="nx-form-input nx-form-textarea"
665 rows="<?php echo absint( $s['nx_message_rows'] ?? 4 ); ?>"
666 placeholder="<?php echo esc_attr( $s['nx_message_placeholder'] ?? '' ); ?>"
667 <?php if ( ! empty( $s['nx_message_required'] ) ) echo 'required'; ?>
668 ></textarea>
669 </div>
670 <?php endif; ?>
671
672 <div class="<?php echo esc_attr( $this->row_width_classes( $s, 'nx_submit_width' ) ); ?> nx-form-actions">
673 <button type="submit" class="nx-form-submit">
674 <?php echo esc_html( $s['nx_submit_text'] ?? __( 'Submit', 'notificationx' ) ); ?>
675 </button>
676 </div>
677
678 </div>
679
680 <div class="nx-form-message" role="status" aria-live="polite"></div>
681 </form>
682 </div>
683 <?php
684 }
685 }
686