PluginProbe
Booking Calendar / 11.7
Booking Calendar v11.7
11.8.4 11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 All 204 releases
booking / includes / page-form-builder / admin-page-tpl / _src / modal__form_open.js

modal__form_open.js in Booking Calendar 11.7, at includes/page-form-builder/admin-page-tpl/_src/modal__form_open.js

491 lines 13.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Booking Calendar — Load Form modal helper (BFB Admin)
3 *
4 * UI.Modal_Load_Form.open(on_confirm, on_open)
5 *
6 * on_confirm(payload):
7 * payload = { form_slug: string, form: Object|null }
8 *
9 * Depends on:
10 * - UI.Templates.ensure_dom_ref_from_wp_template
11 * - UI.Modals.show/hide
12 * - wpbc_bfb__ajax_list_user_forms()
13 *
14 * @file: ../includes/page-form-builder/admin-page-tpl/_out/modal__form_open.js
15 */
16 (function (w, d) {
17 'use strict';
18
19 const Core = (w.WPBC_BFB_Core = w.WPBC_BFB_Core || {});
20 const UI = (Core.UI = Core.UI || {});
21 UI.Modal_Load_Form = UI.Modal_Load_Form || {};
22
23 // Idempotency guard.
24 if ( UI.Modal_Load_Form.__bound ) {
25 return;
26 }
27 UI.Modal_Load_Form.__bound = true;
28
29 const MODAL_DOM_ID = 'wpbc_bfb_modal__load_form';
30 const TPL_MODAL_ID = 'wpbc-bfb-tpl-modal-load_form';
31
32 const ID_SEARCH = 'wpbc_bfb_popup_modal__load_form__search';
33
34 const SEL_CONFIRM = '#' + MODAL_DOM_ID + ' [data-wpbc-bfb-confirm="1"]';
35 const SEL_CANCEL = '#' + MODAL_DOM_ID + ' [data-wpbc-bfb-cancel="1"]';
36 const SEL_ERROR = '#' + MODAL_DOM_ID + ' [data-wpbc-bfb-error="1"]';
37
38 function has_text(v) {
39 return !! (v && String( v ).trim());
40 }
41
42 function get_el(id) {
43 return d.getElementById( id );
44 }
45
46 function get_modal_el() {
47 return d.getElementById( MODAL_DOM_ID );
48 }
49
50 function set_error(msg) {
51 const modal_el = get_modal_el();
52 const el = modal_el ? modal_el.querySelector( '[data-wpbc-bfb-error="1"]' ) : null;
53 if ( ! el ) {
54 return;
55 }
56
57 if ( has_text( msg ) ) {
58 el.innerHTML = String( msg );
59 el.style.display = '';
60 } else {
61 el.innerHTML = '';
62 el.style.display = 'none';
63 }
64 }
65
66 function set_confirm_enabled(is_enabled) {
67 const modal_el = get_modal_el();
68 const btn = modal_el ? modal_el.querySelector( '[data-wpbc-bfb-confirm="1"]' ) : null;
69 if ( ! btn ) {
70 return;
71 }
72
73 if ( is_enabled ) {
74 btn.classList.remove( 'disabled' );
75 btn.setAttribute( 'aria-disabled', 'false' );
76 } else {
77 btn.classList.add( 'disabled' );
78 btn.setAttribute( 'aria-disabled', 'true' );
79 }
80 }
81
82 function escape_html(s) {
83 return String( s == null ? '' : s )
84 .replace( /&/g, '&' )
85 .replace( /</g, '&lt;' )
86 .replace( />/g, '&gt;' )
87 .replace( /"/g, '&quot;' )
88 .replace( /'/g, '&#039;' );
89 }
90
91 function render_list(modal_el, forms) {
92 const root = modal_el ? modal_el.querySelector( '[data-wpbc-bfb-forms-list="1"]' ) : null;
93 if ( ! root ) {
94 return;
95 }
96
97 let html = '';
98 let any = false;
99
100 for ( let i = 0; i < (forms || []).length; i++ ) {
101 const item = forms[i] || {};
102 const slug = String( item.form_slug || '' );
103 const title = String( item.title || slug || '' );
104 const desc = String( item.description || '' );
105 const pic = String( item.picture_url || item.image_url || '' );
106
107 if ( ! slug ) {
108 continue;
109 }
110 any = true;
111
112 const thumb = pic
113 ? '<img src="' + escape_html( pic ) + '" alt="" />'
114 : '<div class="wpbc_bfb__load_form_item_thumb_blank_img">No image</div>';
115
116 const meta = '<div class="form_item_text_slug">' + escape_html( slug ) + '</div>';
117
118 const line2 = desc ? '<div class="form_item_text_desc">' + escape_html( desc ) + '</div>' : '';
119
120 html += ''
121 + '<div class="wpbc_bfb__load_form_item" data-wpbc-bfb-form-item="1" data-form-slug="' + escape_html( slug ) + '"'
122 + ' >'
123 + ' <div class="wpbc_bfb__load_form_item_thumb">' + thumb + '</div>'
124 + ' <div class="wpbc_bfb__load_form_item_text">'
125 + ' <div class="form_item_text_title">' + escape_html( title ) + '</div>'
126 + meta
127 + line2
128 + ' </div>'
129 + '</div>';
130 }
131
132 if ( ! any ) {
133 html = '<div style="padding:10px;color:#666;">No forms found.</div>';
134 }
135
136 root.innerHTML = html;
137
138 // Re-apply selection highlight if still present on this page.
139 const sel = modal_el.__wpbc_bfb_selected_form_slug || '';
140 if ( sel ) {
141 let found = null;
142 try {
143 found = root.querySelector( '[data-form-slug="' + CSS.escape( sel ) + '"]' );
144 } catch ( _e ) {
145 found = null;
146 }
147 if ( found ) {
148 // found.style.background = '#f6f7f7';
149 found.classList.add( 'wpbc_bfb__load_form_item_selected' );
150 set_confirm_enabled( true );
151 } else {
152 // Selection not on this page anymore -> reset.
153 root.querySelectorAll( '.wpbc_bfb__load_form_item' ).forEach( (el) => {
154 el.classList.remove( 'wpbc_bfb__load_form_item_selected' );
155 } );
156 modal_el.__wpbc_bfb_selected_form_slug = '';
157 set_confirm_enabled( false );
158 }
159 }
160 }
161
162 function set_pager(modal_el, page, has_more) {
163 const pager = modal_el ? modal_el.querySelector( '[data-wpbc-bfb-forms-pager="1"]' ) : null;
164 if ( ! pager ) {
165 return;
166 }
167
168 const prev = pager.querySelector( '[data-wpbc-bfb-page-prev="1"]' );
169 const next = pager.querySelector( '[data-wpbc-bfb-page-next="1"]' );
170 const lab = pager.querySelector( '[data-wpbc-bfb-page-label="1"]' );
171
172 page = parseInt( page || 1, 10 );
173 if ( ! page || page < 1 ) {
174 page = 1;
175 }
176
177 if ( lab ) {
178 lab.textContent = 'Page ' + page;
179 }
180
181 const prev_enabled = (page > 1);
182 const next_enabled = !! has_more;
183
184 function set_btn(btn, enabled) {
185 if ( ! btn ) {
186 return;
187 }
188 if ( enabled ) {
189 btn.classList.remove( 'disabled' );
190 btn.setAttribute( 'aria-disabled', 'false' );
191 } else {
192 btn.classList.add( 'disabled' );
193 btn.setAttribute( 'aria-disabled', 'true' );
194 }
195 }
196
197 set_btn( prev, prev_enabled );
198 set_btn( next, next_enabled );
199 }
200
201 function set_loading(modal_el, is_loading) {
202 const root = modal_el ? modal_el.querySelector( '[data-wpbc-bfb-forms-list="1"]' ) : null;
203 if ( ! root ) {
204 return;
205 }
206
207 if ( is_loading ) {
208 const mainNav = document.querySelector( '.wpbc_bfb_popup_modal__forms_loading_spin_container' ).outerHTML;
209 root.innerHTML = mainNav;
210 // root.innerHTML = '<div class="wpbc_bfb_popup_modal__forms_loading_spin_container" data-wpbc-bfb-forms-loading="1">Loading...</div>'; //.
211 }
212 }
213
214 function bind_handlers(modal_el) {
215 if ( ! modal_el || modal_el.__wpbc_bfb_handlers_bound ) {
216 return;
217 }
218 modal_el.__wpbc_bfb_handlers_bound = true;
219
220 // Click select item (delegated inside list).
221 modal_el.addEventListener( 'click', function (e) {
222 if ( ! e || ! e.target || ! e.target.closest ) {
223 return;
224 }
225
226 const item = e.target.closest( '[data-wpbc-bfb-form-item="1"]' );
227 if ( ! item ) {
228 return;
229 }
230
231 const slug = item.getAttribute( 'data-form-slug' ) || '';
232 modal_el.__wpbc_bfb_selected_form_slug = slug;
233
234 // Visual highlight
235 const root = modal_el.querySelector( '[data-wpbc-bfb-forms-list="1"]' );
236 if ( root ) {
237 const all = root.querySelectorAll( '[data-wpbc-bfb-form-item="1"]' );
238 for ( let i = 0; i < all.length; i++ ) {
239 all[i].style.background = '';
240 }
241 }
242 // item.style.background = '#f6f7f7';
243 root.querySelectorAll( '.wpbc_bfb__load_form_item' ).forEach( (el) => {
244 el.classList.remove( 'wpbc_bfb__load_form_item_selected' );
245 } );
246 item.classList.add( 'wpbc_bfb__load_form_item_selected' );
247 set_confirm_enabled( !! slug );
248 }, true );
249
250 // Search filter. (server-side, debounced).
251 const search_el = get_el( ID_SEARCH );
252 if ( search_el ) {
253 if ( ! modal_el.__wpbc_bfb_search_timer ) {
254 modal_el.__wpbc_bfb_search_timer = 0;
255 }
256
257 search_el.addEventListener( 'input', function () {
258 const v = String( search_el.value || '' );
259
260 if ( modal_el.__wpbc_bfb_search_timer ) {
261 clearTimeout( modal_el.__wpbc_bfb_search_timer );
262 }
263 modal_el.__wpbc_bfb_search_timer = setTimeout( function () {
264 load_forms( modal_el, 1, v );
265 }, 300 );
266 }, true );
267 }
268
269 // Pager click.
270 modal_el.addEventListener( 'click', function (e) {
271 if ( ! e || ! e.target || ! e.target.closest ) {
272 return;
273 }
274
275 const prev = e.target.closest( '[data-wpbc-bfb-page-prev="1"]' );
276 const next = e.target.closest( '[data-wpbc-bfb-page-next="1"]' );
277
278 if ( ! prev && ! next ) {
279 return;
280 }
281
282 e.preventDefault();
283
284 if ( (prev && (prev.classList.contains( 'disabled' ) || prev.getAttribute( 'aria-disabled' ) === 'true')) ||
285 (next && (next.classList.contains( 'disabled' ) || next.getAttribute( 'aria-disabled' ) === 'true')) ) {
286 return;
287 }
288
289 const page = parseInt( modal_el.__wpbc_bfb_page || 1, 10 ) || 1;
290 const search = String( modal_el.__wpbc_bfb_search || '' );
291
292 if ( prev ) {
293 load_forms( modal_el, Math.max( 1, page - 1 ), search );
294 }
295 if ( next ) {
296 load_forms( modal_el, page + 1, search );
297 }
298 }, true );
299
300 }
301
302 function load_forms(modal_el, page, search, done) {
303 if ( typeof w.wpbc_bfb__ajax_list_user_forms !== 'function' ) {
304 set_error( 'WPBC BFB: list forms helper missing.' );
305 set_loading( modal_el, false );
306 if ( typeof done === 'function' ) {
307 done( false, null );
308 }
309 return;
310 }
311
312 page = parseInt( page || 1, 10 );
313 search = String( search || '' );
314
315 if ( ! page || page < 1 ) {
316 page = 1;
317 }
318
319 set_error( '' );
320 set_confirm_enabled( false );
321 modal_el.__wpbc_bfb_selected_form_slug = '';
322 set_loading( modal_el, true );
323
324 w.wpbc_bfb__ajax_list_user_forms(
325 null,
326 {
327 include_global: 0,
328 page : page,
329 limit : 20,
330 search : search
331 },
332 function (ok, data) {
333 if ( ! ok || ! data || ! data.forms ) {
334 set_loading( modal_el, false );
335 set_error( 'Failed to load forms list.' );
336 set_pager( modal_el, 1, false );
337 if ( typeof done === 'function' ) {
338 done( false, null );
339 }
340 return;
341 }
342
343 modal_el.__wpbc_bfb_forms_cache = data.forms || [];
344 modal_el.__wpbc_bfb_page = data.page || page;
345 modal_el.__wpbc_bfb_has_more = !! data.has_more;
346 modal_el.__wpbc_bfb_search = search;
347
348 render_list( modal_el, modal_el.__wpbc_bfb_forms_cache );
349 set_pager( modal_el, modal_el.__wpbc_bfb_page, modal_el.__wpbc_bfb_has_more );
350
351 set_error( '' );
352 if ( typeof done === 'function' ) {
353 done( true, data );
354 }
355 }
356 );
357 }
358
359
360 UI.Modal_Load_Form.open = function (on_confirm, on_open) {
361
362 const ref = UI.Templates.ensure_dom_ref_from_wp_template( TPL_MODAL_ID, MODAL_DOM_ID );
363 if ( ! ref || ! ref.el ) {
364 return;
365 }
366
367 let modal_el = ref.el;
368 if ( modal_el && modal_el.id !== MODAL_DOM_ID ) {
369 const inside = modal_el.querySelector ? modal_el.querySelector( '#' + MODAL_DOM_ID ) : null;
370 if ( inside ) {
371 modal_el = inside;
372 }
373 }
374 if ( ! modal_el ) {
375 return;
376 }
377
378 modal_el.__wpbc_bfb_load_form_cb = (typeof on_confirm === 'function') ? on_confirm : null;
379
380 bind_handlers( modal_el );
381
382 // Reset basic UI.
383 const search_el = get_el( ID_SEARCH );
384 if ( search_el ) {
385 search_el.value = '';
386 }
387 modal_el.__wpbc_bfb_forms_cache = [];
388 modal_el.__wpbc_bfb_selected_form_slug = '';
389 set_error( '' );
390 set_confirm_enabled( false );
391 set_loading( modal_el, true );
392
393 UI.Modals.show( modal_el );
394
395 // Load list via ajax.
396 modal_el.__wpbc_bfb_page = 1;
397 modal_el.__wpbc_bfb_has_more = false;
398 modal_el.__wpbc_bfb_search = '';
399
400 load_forms( modal_el, 1, '' );
401 set_pager( modal_el, 1, false );
402
403 // Focus search.
404 w.setTimeout( function () {
405 const s = get_el( ID_SEARCH );
406 if ( s && s.focus ) {
407 try { s.focus(); } catch ( _e ) {}
408 }
409 }, 0 );
410
411 if ( on_open ) {
412 try { on_open( modal_el ); } catch ( _e2 ) {}
413 }
414 };
415
416 // Confirm / Cancel (delegated).
417 d.addEventListener( 'click', function (e) {
418
419 const modal_el = get_modal_el();
420 if ( ! modal_el || ! e || ! e.target || ! e.target.closest ) {
421 return;
422 }
423
424 const is_confirm = e.target.closest( SEL_CONFIRM );
425 if ( is_confirm ) {
426 e.preventDefault();
427
428 if ( is_confirm.classList.contains( 'disabled' ) || is_confirm.getAttribute( 'aria-disabled' ) === 'true' ) {
429 return;
430 }
431
432 const slug = modal_el.__wpbc_bfb_selected_form_slug || '';
433 if ( ! slug ) {
434 return;
435 }
436
437 const cb = modal_el.__wpbc_bfb_load_form_cb || null;
438 modal_el.__wpbc_bfb_load_form_cb = null;
439
440 UI.Modals.hide( modal_el );
441
442 if ( cb ) {
443 // Try to find selected full object:
444 let full = null;
445 const list = modal_el.__wpbc_bfb_forms_cache || [];
446 for ( let i = 0; i < list.length; i++ ) {
447 if ( String( list[i].form_slug || '' ) === String( slug ) ) {
448 full = list[i];
449 break;
450 }
451 }
452 try { cb( { form_slug: slug, form: full } ); } catch ( _e3 ) {}
453 }
454 return;
455 }
456
457 const is_cancel = e.target.closest( SEL_CANCEL );
458 if ( is_cancel ) {
459 e.preventDefault();
460 modal_el.__wpbc_bfb_load_form_cb = null;
461 UI.Modals.hide( modal_el );
462 }
463
464 }, true );
465
466 })( window, document );
467
468
469 function wpbc_bfb__menu_forms__load(menu_option_this) {
470
471 WPBC_BFB_Core.UI.Modal_Load_Form.open( function (payload) {
472
473 if ( ! payload || ! payload.form_slug ) {
474 return;
475 }
476
477 // Load selected form into builder.
478 if ( typeof window.wpbc_bfb__ajax_load_form_by_slug !== 'function' ) {
479 wpbc_admin_show_message( 'WPBC BFB: load-by-slug helper missing.', 'error', 10000 );
480 return;
481 }
482
483 window.wpbc_bfb__ajax_load_form_by_slug( payload.form_slug, menu_option_this, function (ok, data) {
484 if ( ok ) {
485 wpbc_admin_show_message( 'Form loaded', 'success', 1500, false );
486 }
487 } );
488
489 } );
490 }
491