PluginProbe
Booking Calendar / 11.3
Booking Calendar v11.3
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 / page-settings-themes / _src / settings_themes_page.js

settings_themes_page.js in Booking Calendar 11.3, at includes/page-settings-themes/_src/settings_themes_page.js

504 lines 16.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Appearance / Theme settings page UI.
3 */
4 ( function ( $, w ) {
5 'use strict';
6
7 var cfg = w.wpbc_settings_themes_page || {};
8 var preview_ajax = null;
9 var preview_timer = 0;
10 var preview_notice_timer = 0;
11 var preview_notice_message_timer = 0;
12
13 function trim_text( value ) {
14 return String( value || '' ).trim();
15 }
16
17 function make_asset_url( path ) {
18 path = String( path || '' );
19 if ( /^https?:\/\//i.test( path ) || /^\/\//.test( path ) ) {
20 return path;
21 }
22 return String( cfg.plugin_url || '' ).replace( /\/$/, '' ) + path;
23 }
24
25 function show_message( message, type, delay ) {
26 if ( typeof w.wpbc_admin_show_message === 'function' ) {
27 w.wpbc_admin_show_message( message, type || 'info', delay || 4000, false );
28 }
29 }
30
31 function pulse_element( $element, duration ) {
32 if ( ! $element || ! $element.length ) {
33 return;
34 }
35
36 $element
37 .removeClass( 'wpbc_theme_attention_pulse' )
38 .each( function () {
39 void this.offsetWidth;
40 } )
41 .addClass( 'wpbc_theme_attention_pulse' );
42
43 setTimeout( function () {
44 $element.removeClass( 'wpbc_theme_attention_pulse' );
45 }, duration || 2100 );
46 }
47
48 function pulse_latest_warning_notice() {
49 clearTimeout( preview_notice_message_timer );
50 preview_notice_message_timer = setTimeout( function () {
51 pulse_element( $( '#ajax_working .wpbc_inner_message.notice-warning' ).last() );
52 }, 50 );
53 }
54
55 function show_highlighted_notice( message, type, delay, $control ) {
56 if ( $control && $control.length ) {
57 pulse_element( $control );
58 }
59
60 show_message( message, type || 'warning', delay || 9000 );
61 pulse_latest_warning_notice();
62 }
63
64 function switch_panel( $tab ) {
65 var panel_id = $tab.attr( 'aria-controls' );
66 var $tabs = $tab.closest( '.wpbc_theme_rightbar_tabs' ).find( '[role="tab"]' );
67 var $panels = $( '.wpbc_theme_rightbar_panels [role="tabpanel"]' );
68
69 $tabs.attr( 'aria-selected', 'false' );
70 $tab.attr( 'aria-selected', 'true' );
71
72 $panels.attr( 'hidden', 'hidden' ).attr( 'aria-hidden', 'true' );
73 $( '#' + panel_id ).removeAttr( 'hidden' ).attr( 'aria-hidden', 'false' );
74 }
75
76 function toggle_group( $button ) {
77 var $group = $button.closest( '.wpbc_ui__collapsible_group' );
78 var $fields = $group.find( '> .group__fields' );
79 var is_open = $group.hasClass( 'is-open' );
80
81 $group.toggleClass( 'is-open', ! is_open );
82 $button.attr( 'aria-expanded', is_open ? 'false' : 'true' );
83 $fields.prop( 'hidden', is_open ).attr( 'aria-hidden', is_open ? 'true' : 'false' );
84 }
85
86 function get_form() {
87 return $( '[data-wpbc-theme-settings-form="1"]' ).first();
88 }
89
90 function collect_payload() {
91 var $form = get_form();
92 var data = {};
93
94 $.each( $form.serializeArray(), function ( index, item ) {
95 data[ item.name ] = item.value;
96 } );
97
98 data.booking_timeslot_picker = $form.find( '[name="booking_timeslot_picker"]' ).prop( 'checked' ) ? 'On' : 'Off';
99 data.resource_id = $( '#wpbc_theme_resource_id' ).val() || '';
100 data.months_count = $( '#wpbc_theme_months_count' ).val() || '';
101 data.preview_mode = $( '#wpbc_theme_preview_mode' ).val() || 'calendar';
102 data.custom_booking_form = $( '#wpbc_theme_custom_form' ).val() || 'standard';
103
104 return data;
105 }
106
107 function apply_form_theme() {
108 var theme = get_form().find( '[name="booking_form_theme"]:checked' ).val() || '';
109 var $preview = $( '[data-wpbc-theme-preview="1"]' );
110
111 $preview.removeClass( 'wpbc_theme_dark_1' );
112 if ( theme ) {
113 $preview.addClass( theme );
114 }
115
116 $( '.wpbc_theme_choice' ).removeClass( 'is-selected' );
117 get_form().find( '[name="booking_form_theme"]:checked' ).closest( '.wpbc_theme_choice' ).addClass( 'is-selected' );
118 }
119
120 function apply_calendar_skin() {
121 var $select = $( '[data-wpbc-theme-calendar-skin="1"]' );
122 var value = $select.find( 'option:selected' ).attr( 'data-wpbc-calendar-skin-url' ) || $select.val() || '';
123 var skin_url = value ? make_asset_url( value ) : '';
124
125 if ( skin_url && typeof w.wpbc__calendar__change_skin === 'function' && $( '#wpbc-calendar-skin-css' ).length ) {
126 w.wpbc__calendar__change_skin( skin_url );
127 }
128 }
129
130 function apply_time_skin() {
131 var value = $( '[data-wpbc-theme-time-skin="1"]' ).val() || '';
132 var skin_url = value ? make_asset_url( value ) : '';
133
134 if ( skin_url && typeof w.wpbc__css__change_skin === 'function' && $( '#wpbc-time_picker-skin-css' ).length ) {
135 w.wpbc__css__change_skin( skin_url, 'wpbc-time_picker-skin-css' );
136 }
137 }
138
139 function select_if_option_exists( $select, value ) {
140 var $option;
141
142 if ( ! $select.length || ! value ) {
143 return false;
144 }
145
146 $option = $select.find( 'option[value="' + value + '"]' );
147 if ( ! $option.length ) {
148 return false;
149 }
150
151 if ( $select.val() === value ) {
152 return false;
153 }
154
155 $select.val( value ).trigger( 'change' );
156 return true;
157 }
158
159 function parse_number_list( value ) {
160 if ( Array.isArray( value ) ) {
161 return $.map( value, function ( item ) {
162 var parsed = parseInt( item, 10 );
163 return isNaN( parsed ) ? null : parsed;
164 } );
165 }
166
167 return $.map( String( value || '' ).split( /\s*,\s*/ ), function ( item ) {
168 var parsed = parseInt( item, 10 );
169 return ( '' === item || isNaN( parsed ) ) ? null : parsed;
170 } );
171 }
172
173 function set_calendar_param( resource_id, key, value ) {
174 if ( w._wpbc && typeof w._wpbc.calendar__set_param_value === 'function' ) {
175 w._wpbc.calendar__set_param_value( resource_id, key, value );
176 }
177 }
178
179 function apply_days_selection_to_calendar( resource_id, days_selection, should_reinit ) {
180 var ds = days_selection || {};
181 var fixed_week_days;
182 var dynamic_specific;
183 var dynamic_week_days;
184
185 if ( ! resource_id || ! w._wpbc || typeof w._wpbc.calendar__set_param_value !== 'function' ) {
186 return;
187 }
188
189 fixed_week_days = parse_number_list( ds.fixed__week_days__start );
190 dynamic_specific = parse_number_list( ds.dynamic__days_specific );
191 dynamic_week_days = parse_number_list( ds.dynamic__week_days__start );
192
193 set_calendar_param( resource_id, 'days_select_mode', String( ds.days_select_mode || 'multiple' ) );
194 set_calendar_param( resource_id, 'fixed__days_num', parseInt( ds.fixed__days_num || 0, 10 ) );
195 set_calendar_param( resource_id, 'fixed__week_days__start', fixed_week_days.length ? fixed_week_days : [ -1 ] );
196 set_calendar_param( resource_id, 'dynamic__days_min', parseInt( ds.dynamic__days_min || 0, 10 ) );
197 set_calendar_param( resource_id, 'dynamic__days_max', parseInt( ds.dynamic__days_max || 0, 10 ) );
198 set_calendar_param( resource_id, 'dynamic__days_specific', dynamic_specific );
199 set_calendar_param( resource_id, 'dynamic__week_days__start', dynamic_week_days.length ? dynamic_week_days : [ -1 ] );
200
201 if ( typeof w.wpbc__conditions__SAVE_INITIAL__days_selection_params__bm === 'function' ) {
202 w.wpbc__conditions__SAVE_INITIAL__days_selection_params__bm( resource_id );
203 }
204
205 if ( should_reinit && typeof w.wpbc_cal__re_init === 'function' ) {
206 w.wpbc_cal__re_init( resource_id );
207 }
208 }
209
210 function ensure_calendar_only_days_selection() {
211 var $preview = $( '[data-wpbc-theme-preview="1"]' ).first();
212 var preview_mode = $preview.attr( 'data-preview-mode' ) || $( '#wpbc_theme_preview_mode' ).val() || 'calendar';
213 var resource_id = parseInt( $preview.attr( 'data-resource-id' ) || 0, 10 );
214 var expected = cfg.days_selection || {};
215 var expected_mode = String( expected.days_select_mode || 'multiple' );
216 var current_mode = null;
217 var $calendar;
218 var should_reinit = false;
219
220 if ( 'calendar' !== preview_mode || ! resource_id || ! expected_mode ) {
221 return;
222 }
223
224 if ( ! w._wpbc || typeof w._wpbc.calendar__get_param_value !== 'function' ) {
225 return;
226 }
227
228 current_mode = w._wpbc.calendar__get_param_value( resource_id, 'days_select_mode' );
229 if ( String( current_mode || '' ) === expected_mode ) {
230 return;
231 }
232
233 $calendar = $( '#calendar_booking' + resource_id );
234 should_reinit = $calendar.length && $calendar.hasClass( 'hasDatepick' );
235
236 apply_days_selection_to_calendar( resource_id, expected, should_reinit );
237 }
238
239 function apply_related_skins_for_theme( theme ) {
240 var calendar_skin = theme ? '/css/skins/24_9__dark_1.css' : '/css/skins/25_5__square_1.css';
241 var time_skin = theme ? '/css/time_picker_skins/black.css' : '/css/time_picker_skins/light__24_8.css';
242
243 select_if_option_exists( $( '[data-wpbc-theme-calendar-skin="1"]' ), calendar_skin );
244 select_if_option_exists( $( '[data-wpbc-theme-time-skin="1"]' ), time_skin );
245 }
246
247 function pulse_preview_mode_control() {
248 var $control = $( '.wpbc_theme_control_preview_mode' ).first();
249
250 pulse_element( $control );
251
252 clearTimeout( preview_notice_timer );
253 preview_notice_timer = setTimeout( function () {
254 $control.removeClass( 'wpbc_theme_attention_pulse' );
255 }, 2100 );
256 }
257
258 function get_preview_notice_message( notice_type ) {
259 var i18n = cfg.i18n || {};
260
261 if ( 'form' === notice_type ) {
262 return i18n.form_preview_option_notice || 'This option is visible in the Booking form preview. Switch Preview to Booking form to inspect it.';
263 }
264
265 return '';
266 }
267
268 function maybe_show_preview_notice( $source ) {
269 var notice_type = $source.attr( 'data-wpbc-theme-preview-notice' ) || '';
270 var preview_mode = $( '#wpbc_theme_preview_mode' ).val() || 'calendar';
271 var message = get_preview_notice_message( notice_type );
272 var $control = $( '.wpbc_theme_control_preview_mode' ).first();
273
274 if ( ! message ) {
275 return;
276 }
277
278 if ( 'form' === notice_type && 'calendar' !== preview_mode ) {
279 return;
280 }
281
282 if ( 'form' === notice_type ) {
283 pulse_preview_mode_control();
284 show_highlighted_notice( message, 'warning', 9000 );
285 return;
286 }
287
288 show_highlighted_notice( message, 'warning', 9000, $control );
289 }
290
291 function show_calendar_only_theme_notice() {
292 var preview_mode = $( '#wpbc_theme_preview_mode' ).val() || 'calendar';
293
294 if ( 'calendar' !== preview_mode ) {
295 return;
296 }
297
298 pulse_preview_mode_control();
299 show_highlighted_notice(
300 cfg.i18n && cfg.i18n.calendar_only_theme_notice ? cfg.i18n.calendar_only_theme_notice : 'Preview is set to Calendar only. Switch Preview to Booking form to inspect the form theme.',
301 'warning',
302 9000
303 );
304 }
305
306 function sync_time_picker_preview() {
307 var is_enabled = get_form().find( '[name="booking_timeslot_picker"]' ).prop( 'checked' );
308 var $preview = $( '[data-wpbc-theme-preview="1"]' );
309 var time_selectors = 'select[name^="rangetime"], select[name^="starttime"], select[name^="endtime"], select[name^="durationtime"]';
310
311 if ( w._wpbc && typeof w._wpbc.set_other_param === 'function' ) {
312 w._wpbc.set_other_param( 'is_enabled_booking_timeslot_picker', !! is_enabled );
313 }
314
315 if ( is_enabled ) {
316 if ( w._wpbc && typeof w.wpbc_hook__init_timeselector === 'function' ) {
317 w.wpbc_hook__init_timeselector();
318 }
319 return;
320 }
321
322 $preview.find( '.wpbc_times_selector' ).remove();
323 $preview.find( time_selectors ).show();
324 }
325
326 function refresh_preview_mode_controls() {
327 var preview_mode = $( '#wpbc_theme_preview_mode' ).val() || 'calendar';
328 $( '[data-wpbc-theme-form-control="1"]' ).toggleClass( 'is-visible', 'form' === preview_mode );
329 }
330
331 function set_calendar_loading( is_loading ) {
332 var $panel = $( '[data-wpbc-theme-calendar-panel="1"]' );
333
334 $panel.toggleClass( 'is-loading', !! is_loading );
335 $panel.find( '.wpbc_theme_calendar_loading' ).remove();
336
337 if ( is_loading ) {
338 $panel.append(
339 '<div class="wpbc_calendar_loading wpbc_theme_calendar_loading">' +
340 '<span class="wpbc_icn_autorenew wpbc_animation_spin"></span>&nbsp;' +
341 trim_text( cfg.i18n && cfg.i18n.loading ? cfg.i18n.loading : 'Loading' ) +
342 '</div>'
343 );
344 }
345 }
346
347 function refresh_preview() {
348 var data = collect_payload();
349
350 if ( preview_ajax && preview_ajax.readyState !== 4 ) {
351 preview_ajax.abort();
352 }
353
354 data.action = cfg.preview_action;
355 data.nonce = cfg.nonce;
356
357 set_calendar_loading( true );
358 preview_ajax = $.post( cfg.ajax_url, data )
359 .done( function ( response ) {
360 if ( response && response.success && response.data && response.data.html ) {
361 $( '[data-wpbc-theme-preview="1"]' ).replaceWith( response.data.html );
362 if ( response.data.days_selection ) {
363 cfg.days_selection = response.data.days_selection;
364 }
365 apply_form_theme();
366 apply_calendar_skin();
367 apply_time_skin();
368 ensure_calendar_only_days_selection();
369 sync_time_picker_preview();
370 return;
371 }
372
373 show_message(
374 response && response.data && response.data.message ? response.data.message : ( cfg.i18n && cfg.i18n.preview_failed ? cfg.i18n.preview_failed : 'Unable to refresh calendar preview.' ),
375 'error',
376 10000
377 );
378 } )
379 .fail( function ( xhr, text_status ) {
380 if ( 'abort' === text_status ) {
381 return;
382 }
383 show_message( cfg.i18n && cfg.i18n.preview_failed ? cfg.i18n.preview_failed : 'Unable to refresh calendar preview.', 'error', 10000 );
384 } )
385 .always( function () {
386 set_calendar_loading( false );
387 } );
388 }
389
390 function schedule_preview_refresh() {
391 clearTimeout( preview_timer );
392 preview_timer = setTimeout( refresh_preview, 180 );
393 }
394
395 function save_settings() {
396 var $button = $( '[data-wpbc-theme-save="1"]' );
397 var original_text = $button.data( 'wpbc-original-text' );
398 var data = collect_payload();
399
400 if ( ! original_text ) {
401 original_text = $button.html();
402 $button.data( 'wpbc-original-text', original_text );
403 }
404
405 data.action = cfg.action;
406 data.nonce = cfg.nonce;
407
408 $button.addClass( 'disabled' ).attr( 'aria-disabled', 'true' );
409 $button.find( '.in-button-text' ).html( '&nbsp;&nbsp;' + trim_text( cfg.i18n && cfg.i18n.saving ? cfg.i18n.saving : 'Saving' ) + '...' );
410
411 $.post( cfg.ajax_url, data )
412 .done( function ( response ) {
413 if ( response && response.success ) {
414 show_message( response.data && response.data.message ? response.data.message : ( cfg.i18n && cfg.i18n.saved ? cfg.i18n.saved : 'Saved' ), 'success', 3000 );
415 cfg.settings = response.data && response.data.settings ? response.data.settings : cfg.settings;
416 return;
417 }
418
419 show_message(
420 response && response.data && response.data.message ? response.data.message : ( cfg.i18n && cfg.i18n.save_failed ? cfg.i18n.save_failed : 'Unable to save appearance settings.' ),
421 'error',
422 10000
423 );
424 } )
425 .fail( function () {
426 show_message( cfg.i18n && cfg.i18n.save_failed ? cfg.i18n.save_failed : 'Unable to save appearance settings.', 'error', 10000 );
427 } )
428 .always( function () {
429 $button.removeClass( 'disabled' ).removeAttr( 'aria-disabled' ).html( original_text );
430 } );
431 }
432
433 function bind_events() {
434 $( document ).on( 'click', '.wpbc_theme_rightbar_tabs [role="tab"]', function ( event ) {
435 event.preventDefault();
436 switch_panel( $( this ) );
437 } );
438
439 $( document ).on( 'click', '.wpbc_theme_premium_dismiss a', function ( event ) {
440 event.stopPropagation();
441 } );
442
443 $( document ).on( 'click', '.wpbc_theme_rightbar_panels .wpbc_ui__collapsible_group > .group__header', function ( event ) {
444 event.preventDefault();
445 toggle_group( $( this ) );
446 } );
447
448 $( document ).on( 'click', '[data-wpbc-theme-save="1"]', function ( event ) {
449 event.preventDefault();
450 if ( ! $( this ).hasClass( 'disabled' ) ) {
451 save_settings();
452 }
453 } );
454
455 $( document ).on( 'submit', '[data-wpbc-theme-settings-form="1"]', function () {
456 return true;
457 } );
458
459 $( document ).on( 'change', '[name="booking_form_theme"]', function () {
460 apply_form_theme();
461 apply_related_skins_for_theme( $( this ).val() || '' );
462 show_calendar_only_theme_notice();
463 } );
464
465 $( document ).on( 'change', '[data-wpbc-theme-calendar-skin="1"]', function () {
466 apply_calendar_skin();
467 } );
468
469 $( document ).on( 'change', '[data-wpbc-theme-time-skin="1"]', function () {
470 apply_time_skin();
471 } );
472
473 $( document ).on( 'change', '[name="booking_timeslot_picker"]', function () {
474 sync_time_picker_preview();
475 schedule_preview_refresh();
476 } );
477
478 $( document ).on( 'change', '[data-wpbc-theme-preview-notice]', function () {
479 maybe_show_preview_notice( $( this ) );
480 } );
481
482 $( document ).on( 'change', '#wpbc_theme_resource_id, #wpbc_theme_months_count, #wpbc_theme_custom_form', function () {
483 schedule_preview_refresh();
484 } );
485
486 $( document ).on( 'change', '#wpbc_theme_preview_mode', function () {
487 refresh_preview_mode_controls();
488 schedule_preview_refresh();
489 } );
490 }
491
492 $( function () {
493 if ( ! $( '[data-wpbc-theme-page="1"]' ).length ) {
494 return;
495 }
496
497 bind_events();
498 refresh_preview_mode_controls();
499 apply_form_theme();
500 ensure_calendar_only_days_selection();
501 sync_time_picker_preview();
502 } );
503 }( jQuery, window ) );
504