PluginProbe
Booking Calendar / 11.6
Booking Calendar v11.6
11.9 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 All 205 releases
booking / includes / publish / _src / wpbc-publish-booking-form.js

wpbc-publish-booking-form.js in Booking Calendar 11.6, at includes/publish/_src/wpbc-publish-booking-form.js

392 lines 12.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Neutral Booking Form publishing modal controller.
3 *
4 * @package Booking Calendar
5 * @since 11.6.0
6 */
7 ( function( $, window, document ) {
8 'use strict';
9
10 var last_trigger = null;
11 var pages_request = null;
12
13 /**
14 * Return localized publishing configuration.
15 *
16 * @return {Object} Publishing configuration.
17 */
18 function get_config() {
19 return window.wpbc_publish_booking_form_vars || {};
20 }
21
22 /**
23 * Normalize a localized WordPress flag to a strict boolean.
24 *
25 * wp_localize_script() serializes scalar configuration values as strings,
26 * so the disabled value arrives as "0", which is otherwise truthy in
27 * JavaScript.
28 *
29 * @param {*} flag_value Localized flag value.
30 *
31 * @return {boolean} True only for an explicitly enabled flag.
32 */
33 function is_true_flag( flag_value ) {
34 return true === flag_value || 1 === flag_value || '1' === flag_value || 'true' === String( flag_value ).toLowerCase();
35 }
36
37 /**
38 * Return the native publishing modal.
39 *
40 * @return {jQuery} Modal element.
41 */
42 function get_modal() {
43 return $( get_config().modal_selector || '#wpbc_publish_booking_form__modal' );
44 }
45
46 /**
47 * Escape plain text before inserting it into status markup.
48 *
49 * @param {string} message Plain text.
50 *
51 * @return {string} Escaped text.
52 */
53 function escape_html( message ) {
54 return $( '<div>' ).text( String( message || '' ) ).html();
55 }
56
57 /**
58 * Extract a sanitized Booking Form name from a shortcode.
59 *
60 * @param {string} shortcode_raw Raw Booking shortcode.
61 *
62 * @return {string} Sanitized form name.
63 */
64 function get_form_name( shortcode_raw ) {
65 var match = String( shortcode_raw || '' ).match( /\bform_type\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s\]]+))/i );
66 var form_name = match ? ( match[ 1 ] || match[ 2 ] || match[ 3 ] || '' ) : '';
67
68 form_name = String( form_name ).toLowerCase().replace( /[^a-z0-9_-]/g, '' );
69
70 return form_name || 'standard';
71 }
72
73 /**
74 * Reset the modal to its initial chooser state.
75 *
76 * @return {void}
77 */
78 function reset_modal() {
79 var $modal = get_modal();
80 var $page_list = $modal.find( '[data-wpbc-publish-booking-form-page-list]' );
81
82 if ( pages_request && 'function' === typeof pages_request.abort ) {
83 pages_request.abort();
84 }
85 pages_request = null;
86
87 $modal.find( '.wpbc_publish_booking_form__notice' ).empty();
88 $modal.find( '.wpbc_publish_booking_form__panel' ).hide();
89 $modal.find( '.wpbc_publish_booking_form__result_actions' ).hide();
90 $modal.find( '[data-wpbc-publish-booking-form-open-page], [data-wpbc-publish-booking-form-edit-page]' ).hide().attr( 'href', '#' );
91 $modal.find( '.wpbc_publish_booking_form__chooser' ).show();
92 $modal.find( '.modal-footer' ).hide();
93 $page_list.find( 'option:not(:first)' ).remove();
94 $page_list.val( '0' ).prop( 'disabled', true );
95 $modal.find( '#wpbc_publish_booking_form_page_title' ).val( '' );
96 set_busy( false );
97 }
98
99 /**
100 * Toggle all publishing controls while a request is active.
101 *
102 * @param {boolean} is_busy Whether publishing is active.
103 *
104 * @return {void}
105 */
106 function set_busy( is_busy ) {
107 get_modal().find( '[data-wpbc-publish-booking-form-mode], [data-wpbc-publish-booking-form-submit], [data-wpbc-publish-booking-form-back]' )
108 .prop( 'disabled', Boolean( is_busy ) )
109 .attr( 'aria-disabled', is_busy ? 'true' : 'false' );
110 }
111
112 /**
113 * Render a plain error inside the native modal.
114 *
115 * @param {string} message Error message.
116 *
117 * @return {void}
118 */
119 function show_error( message ) {
120 get_modal().find( '.wpbc_publish_booking_form__notice' ).html(
121 '<div class="wpbc-settings-notice notice-error">' + escape_html( message ) + '</div>'
122 );
123 }
124
125 /**
126 * Show the Booking Calendar mini spinner and loading label.
127 *
128 * @return {void}
129 */
130 function show_loading( loading_message ) {
131 var i18n = get_config().i18n || {};
132
133 get_modal().find( '.wpbc_publish_booking_form__notice' ).html(
134 '<div class="wpbc_spins_loading_container wpbc_publish_booking_form__loading" role="status">' +
135 '<div class="wpbc_booking_form_spin_loader" aria-hidden="true"><div class="wpbc_spins_loader_wrapper"><div class="wpbc_one_spin_loader_mini2"></div></div></div>' +
136 '<span>' + escape_html( loading_message || i18n.loading || 'Publishing booking form' ) + '...</span>' +
137 '</div>'
138 );
139 }
140
141 /**
142 * Load the editable WordPress pages through the authorized endpoint.
143 *
144 * Page titles are intentionally absent from the initial catalog markup. The
145 * live-demo guard runs before this request on the client and again before the
146 * page query on the server.
147 *
148 * @return {void}
149 */
150 function load_publishable_pages() {
151 var config = get_config();
152 var i18n = config.i18n || {};
153 var $modal = get_modal();
154 var $page_list = $modal.find( '[data-wpbc-publish-booking-form-page-list]' );
155
156 if ( is_true_flag( config.is_demo ) ) {
157 show_error( i18n.demo_error || 'In the demo versions this operation is not allowed.' );
158 return;
159 }
160
161 set_busy( true );
162 show_loading( i18n.loading_pages || 'Loading pages' );
163
164 pages_request = $.ajax(
165 {
166 url: config.ajax_url || window.ajaxurl || '',
167 method: 'POST',
168 dataType: 'json',
169 data: {
170 action: config.pages_action || 'WPBC_AJX_GET_PUBLISHABLE_PAGES',
171 nonce: config.nonce || ''
172 }
173 }
174 ).done(
175 function( response ) {
176 var result = response && response.data ? response.data : {};
177 var pages = $.isArray( result.pages ) ? result.pages : [];
178
179 if ( ! response || ! response.success ) {
180 show_error( result.message || i18n.generic_error || 'Unable to load pages.' );
181 return;
182 }
183
184 $page_list.find( 'option:not(:first)' ).remove();
185 $.each(
186 pages,
187 function( index, page ) {
188 $( '<option>' ).val( parseInt( page.id, 10 ) || 0 ).text( String( page.title || '' ) ).appendTo( $page_list );
189 }
190 );
191
192 $modal.find( '.wpbc_publish_booking_form__notice' ).empty();
193 $page_list.prop( 'disabled', ! pages.length );
194 if ( pages.length ) {
195 $page_list.trigger( 'focus' );
196 } else {
197 show_error( i18n.no_pages || 'No editable pages are available.' );
198 }
199 }
200 ).fail(
201 function( xhr, request_status ) {
202 var response = xhr && xhr.responseJSON ? xhr.responseJSON : {};
203 var result = response && response.data ? response.data : {};
204
205 if ( 'abort' !== request_status ) {
206 show_error( result.message || i18n.generic_error || 'Unable to load pages.' );
207 }
208 }
209 ).always(
210 function() {
211 pages_request = null;
212 set_busy( false );
213 }
214 );
215 }
216
217 /**
218 * Open one create or edit panel.
219 *
220 * @param {string} publish_mode Create or edit.
221 *
222 * @return {void}
223 */
224 function open_mode( publish_mode ) {
225 var $modal = get_modal();
226 var $panel;
227
228 if ( 'create' !== publish_mode && 'edit' !== publish_mode ) {
229 return;
230 }
231
232 $modal.find( '.wpbc_publish_booking_form__notice' ).empty();
233 $modal.find( '.wpbc_publish_booking_form__chooser, .wpbc_publish_booking_form__panel, .wpbc_publish_booking_form__result_actions' ).hide();
234 $panel = $modal.find( '.wpbc_publish_booking_form__panel--' + publish_mode ).show();
235 $modal.find( '.modal-footer' ).show();
236 if ( 'edit' === publish_mode ) {
237 load_publishable_pages();
238 } else {
239 $panel.find( 'select, input, button' ).filter( ':visible' ).first().trigger( 'focus' );
240 }
241 }
242
243 /**
244 * Return the chooser without closing the modal.
245 *
246 * @return {void}
247 */
248 function go_back() {
249 reset_modal();
250 get_modal().find( '[data-wpbc-publish-booking-form-mode="edit"]' ).trigger( 'focus' );
251 }
252
253 /**
254 * Publish the current Resource shortcode through the neutral endpoint.
255 *
256 * @param {string} publish_mode Create or edit.
257 *
258 * @return {void}
259 */
260 function submit_publish( publish_mode ) {
261 var config = get_config();
262 var i18n = config.i18n || {};
263 var $modal = get_modal();
264 var request_data = {
265 action: config.action || 'WPBC_AJX_PUBLISH_BOOKING_FORM',
266 nonce: config.nonce || '',
267 publish_mode: publish_mode,
268 resource_id: $modal.find( '[data-wpbc-publish-booking-form-resource-id]' ).val() || 0,
269 form_name: $modal.find( '[data-wpbc-publish-booking-form-form-name]' ).val() || 'standard',
270 shortcode_raw: $modal.find( '[data-wpbc-publish-booking-form-shortcode]' ).val() || '',
271 page_id: $modal.find( '#wpbc_publish_booking_form_page_id' ).val() || 0,
272 page_title: $modal.find( '#wpbc_publish_booking_form_page_title' ).val() || ''
273 };
274
275 if ( is_true_flag( config.is_demo ) ) {
276 show_error( i18n.demo_error || 'In the demo versions this operation is not allowed.' );
277 return;
278 }
279 if ( 'edit' === publish_mode && ! parseInt( request_data.page_id, 10 ) ) {
280 show_error( i18n.select_page || 'Please select an existing page.' );
281 return;
282 }
283 if ( 'create' === publish_mode && ! $.trim( request_data.page_title ) ) {
284 show_error( i18n.enter_page_title || 'Please enter a page title.' );
285 return;
286 }
287
288 set_busy( true );
289 show_loading( i18n.loading || 'Publishing booking form' );
290
291 $.ajax(
292 {
293 url: config.ajax_url || window.ajaxurl || '',
294 method: 'POST',
295 dataType: 'json',
296 data: request_data
297 }
298 ).done(
299 function( response ) {
300 var result = response && response.data ? response.data : {};
301
302 if ( ! response || ! response.success ) {
303 show_error( result.message || i18n.generic_error || 'Unable to publish the booking form.' );
304 return;
305 }
306
307 $modal.find( '.wpbc_publish_booking_form__notice' ).html(
308 '<div class="wpbc-settings-notice notice-success">' + ( result.message || '' ) + '</div>'
309 );
310 $modal.find( '.wpbc_publish_booking_form__chooser, .wpbc_publish_booking_form__panel' ).hide();
311 $modal.find( '.modal-footer' ).hide();
312
313 if ( result.view_url ) {
314 $modal.find( '[data-wpbc-publish-booking-form-open-page]' ).attr( 'href', result.view_url ).show();
315 }
316 if ( result.edit_url ) {
317 $modal.find( '[data-wpbc-publish-booking-form-edit-page]' ).attr( 'href', result.edit_url ).show();
318 }
319 $modal.find( '.wpbc_publish_booking_form__result_actions' ).show().find( 'a:visible' ).first().trigger( 'focus' );
320 }
321 ).fail(
322 function( xhr ) {
323 var response = xhr && xhr.responseJSON ? xhr.responseJSON : {};
324 var result = response && response.data ? response.data : {};
325
326 show_error( result.message || i18n.generic_error || 'Unable to publish the booking form.' );
327 }
328 ).always(
329 function() {
330 set_busy( false );
331 }
332 );
333 }
334
335 /**
336 * Open the neutral publishing modal for one Booking Resource.
337 *
338 * @param {number|string} resource_id Booking Resource ID.
339 * @param {string} shortcode_raw Raw Booking shortcode.
340 * @param {HTMLElement} trigger Optional opening control.
341 *
342 * @return {void}
343 */
344 function open_modal( resource_id, shortcode_raw, trigger ) {
345 var config = get_config();
346 var i18n = config.i18n || {};
347 var $modal = get_modal();
348
349 if ( ! $modal.length || 'function' !== typeof $modal.wpbc_my_modal ) {
350 window.alert( i18n.generic_error || 'Publishing dialog is not available.' );
351 return;
352 }
353
354 last_trigger = trigger && document.contains( trigger ) ? trigger : document.activeElement;
355 reset_modal();
356 $modal.find( '[data-wpbc-publish-booking-form-resource-id]' ).val( parseInt( resource_id, 10 ) || 0 );
357 $modal.find( '[data-wpbc-publish-booking-form-form-name]' ).val( get_form_name( shortcode_raw ) );
358 $modal.find( '[data-wpbc-publish-booking-form-shortcode]' ).val( String( shortcode_raw || '' ) );
359
360 $modal.off( 'hidden.wpbc.modal.wpbcPublishBookingForm hidden.bs.modal.wpbcPublishBookingForm' )
361 .one(
362 'hidden.wpbc.modal.wpbcPublishBookingForm hidden.bs.modal.wpbcPublishBookingForm',
363 function() {
364 if ( last_trigger && document.contains( last_trigger ) ) {
365 last_trigger.focus();
366 }
367 last_trigger = null;
368 }
369 );
370
371 $modal.wpbc_my_modal( 'show' );
372 window.setTimeout(
373 function() {
374 $modal.find( '[data-wpbc-publish-booking-form-mode="edit"]' ).trigger( 'focus' );
375 },
376 0
377 );
378 }
379
380 $( document ).on( 'click', '[data-wpbc-publish-booking-form-mode]', function() {
381 open_mode( $( this ).attr( 'data-wpbc-publish-booking-form-mode' ) || '' );
382 } );
383 $( document ).on( 'click', '[data-wpbc-publish-booking-form-submit]', function() {
384 submit_publish( $( this ).attr( 'data-wpbc-publish-booking-form-submit' ) || '' );
385 } );
386 $( document ).on( 'click', '[data-wpbc-publish-booking-form-back]', function() {
387 go_back();
388 } );
389
390 window.wpbc_publish_booking_form__open = open_modal;
391 }( jQuery, window, document ) );
392