PluginProbe
Booking Calendar / 11.8.1
Booking Calendar v11.8.1
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 10.11.2 10.11.3 All 202 releases
booking / includes / page-availability / _src / availability_page.js

availability_page.js in Booking Calendar 11.8.1, at includes/page-availability/_src/availability_page.js

1,092 lines 44.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 "use strict";
2
3 /**
4 * Request Object
5 * Here we can define Search parameters and Update it later, when some parameter was changed
6 *
7 */
8
9 var wpbc_ajx_availability = (function ( obj, $) {
10
11 // Secure parameters for Ajax ------------------------------------------------------------------------------------
12 var p_secure = obj.security_obj = obj.security_obj || {
13 user_id: 0,
14 nonce : '',
15 locale : ''
16 };
17
18 obj.set_secure_param = function ( param_key, param_val ) {
19 p_secure[ param_key ] = param_val;
20 };
21
22 obj.get_secure_param = function ( param_key ) {
23 return p_secure[ param_key ];
24 };
25
26
27 // Listing Search parameters ------------------------------------------------------------------------------------
28 var p_listing = obj.search_request_obj = obj.search_request_obj || {
29 // sort : "booking_id",
30 // sort_type : "DESC",
31 // page_num : 1,
32 // page_items_count: 10,
33 // create_date : "",
34 // keyword : "",
35 // source : ""
36 };
37
38 obj.search_set_all_params = function ( request_param_obj ) {
39 p_listing = request_param_obj;
40 };
41
42 obj.search_get_all_params = function () {
43 return p_listing;
44 };
45
46 obj.search_get_param = function ( param_key ) {
47 return p_listing[ param_key ];
48 };
49
50 obj.search_set_param = function ( param_key, param_val ) {
51 // if ( Array.isArray( param_val ) ){
52 // param_val = JSON.stringify( param_val );
53 // }
54 p_listing[ param_key ] = param_val;
55 };
56
57 obj.search_set_params_arr = function( params_arr ){
58 _.each( params_arr, function ( p_val, p_key, p_data ){ // Define different Search parameters for request
59 this.search_set_param( p_key, p_val );
60 } );
61 }
62
63
64 // Other parameters ------------------------------------------------------------------------------------
65 var p_other = obj.other_obj = obj.other_obj || { };
66
67 obj.set_other_param = function ( param_key, param_val ) {
68 p_other[ param_key ] = param_val;
69 };
70
71 obj.get_other_param = function ( param_key ) {
72 return p_other[ param_key ];
73 };
74
75
76 return obj;
77 }( wpbc_ajx_availability || {}, jQuery ));
78
79 var wpbc_ajx_bookings = [];
80
81 /**
82 * Show Content ---------------------------------------------------------------------------------------------- */
83
84 /**
85 * Show Content - Calendar and UI elements
86 *
87 * @param ajx_data_arr
88 * @param ajx_search_params
89 * @param ajx_cleaned_params
90 */
91 function wpbc_ajx_availability__page_content__show( ajx_data_arr, ajx_search_params , ajx_cleaned_params ){
92
93 var template__availability_main_page_content = wp.template( 'wpbc_ajx_availability_main_page_content' );
94
95 // Content
96 jQuery( wpbc_ajx_availability.get_other_param( 'listing_container' ) ).html( template__availability_main_page_content( {
97 'ajx_data' : ajx_data_arr,
98 'ajx_search_params' : ajx_search_params, // $_REQUEST[ 'search_params' ]
99 'ajx_cleaned_params' : ajx_cleaned_params
100 } ) );
101
102 jQuery( '.wpbc_processing.wpbc_spin').parent().parent().parent().parent( '[id^="wpbc_notice_"]' ).hide();
103 // Load calendar
104 wpbc_ajx_availability__calendar__show( {
105 'resource_id' : ajx_cleaned_params.resource_id,
106 'ajx_nonce_calendar': ajx_data_arr.ajx_nonce_calendar,
107 'ajx_data_arr' : ajx_data_arr,
108 'ajx_cleaned_params' : ajx_cleaned_params
109 } );
110
111
112 /**
113 * Trigger for dates selection in the booking form
114 *
115 * jQuery( wpbc_ajx_availability.get_other_param( 'listing_container' ) ).on('wpbc_page_content_loaded', function(event, ajx_data_arr, ajx_search_params , ajx_cleaned_params) { ... } );
116 */
117 jQuery( wpbc_ajx_availability.get_other_param( 'listing_container' ) ).trigger( 'wpbc_page_content_loaded', [ ajx_data_arr, ajx_search_params , ajx_cleaned_params ] );
118 }
119
120
121 /**
122 * Show inline month view calendar with all predefined CSS (sizes and check in/out, times containers)
123 * @param {obj} calendar_params_arr
124 {
125 'resource_id' : ajx_cleaned_params.resource_id,
126 'ajx_nonce_calendar' : ajx_data_arr.ajx_nonce_calendar,
127 'ajx_data_arr' : ajx_data_arr = { ajx_booking_resources:[], booked_dates: {}, resource_unavailable_dates:[], season_availability:{},.... }
128 'ajx_cleaned_params' : {
129 calendar__days_selection_mode: "dynamic"
130 calendar__start_week_day: "0"
131 calendar__view__cell_height: ""
132 calendar__view__months_in_row: 4
133 calendar__view__visible_months: 12
134 calendar__view__width: "100%"
135
136 dates_availability: "unavailable"
137 dates_selection: "2023-03-14 ~ 2023-03-16"
138 do_action: "set_availability"
139 resource_id: 1
140 ui_clicked_element_id: "wpbc_availability_apply_btn"
141 ui_usr__availability_selected_toolbar: "info"
142 }
143 }
144 */
145 function wpbc_ajx_availability__calendar__show( calendar_params_arr ){
146
147 // Update nonce
148 jQuery( '#ajx_nonce_calendar_section' ).html( calendar_params_arr.ajx_nonce_calendar );
149
150 //------------------------------------------------------------------------------------------------------------------
151 // Update bookings
152 if ( 'undefined' == typeof (wpbc_ajx_bookings[ calendar_params_arr.resource_id ]) ){ wpbc_ajx_bookings[ calendar_params_arr.resource_id ] = []; }
153 wpbc_ajx_bookings[ calendar_params_arr.resource_id ] = calendar_params_arr[ 'ajx_data_arr' ][ 'booked_dates' ];
154
155
156 //------------------------------------------------------------------------------------------------------------------
157 /**
158 * Define showing mouse over tooltip on unavailable dates
159 * It's defined, when calendar REFRESHED (change months or days selection) loaded in jquery.datepick.wpbc.9.0.js :
160 * $( 'body' ).trigger( 'wpbc_datepick_inline_calendar_refresh', ... // FixIn: 9.4.4.13.
161 */
162 jQuery( 'body' ).on( 'wpbc_datepick_inline_calendar_refresh', function ( event, resource_id, inst ){
163 // inst.dpDiv it's: <div class="datepick-inline datepick-multi" style="width: 17712px;">....</div>
164 inst.dpDiv.find( '.season_unavailable,.before_after_unavailable,.weekdays_unavailable' ).on( 'mouseover', function ( this_event ){
165 // also available these vars: resource_id, jCalContainer, inst
166 var jCell = jQuery( this_event.currentTarget );
167 wpbc_avy__show_tooltip__for_element( jCell, calendar_params_arr[ 'ajx_data_arr' ]['popover_hints'] );
168 });
169
170 } );
171
172 //------------------------------------------------------------------------------------------------------------------
173 /**
174 * Define height of the calendar cells, and mouse over tooltips at some unavailable dates
175 * It's defined, when calendar loaded in jquery.datepick.wpbc.9.0.js :
176 * $( 'body' ).trigger( 'wpbc_datepick_inline_calendar_loaded', ... // FixIn: 9.4.4.12.
177 */
178 jQuery( 'body' ).on( 'wpbc_datepick_inline_calendar_loaded', function ( event, resource_id, jCalContainer, inst ){
179
180 // Remove highlight day for today date
181 jQuery( '.datepick-days-cell.datepick-today.datepick-days-cell-over' ).removeClass( 'datepick-days-cell-over' );
182
183 // Set height of calendar cells if defined this option // FixIn: 10.12.4.2.
184 if ( '' !== calendar_params_arr.ajx_cleaned_params.calendar__view__cell_height ){
185 jQuery( 'head' ).append( '<style type="text/css">'
186 + '.hasDatepick .datepick-inline .datepick-title-row th, '
187 + '.hasDatepick .datepick-inline .datepick-days-cell {'
188 + 'max-height: ' + calendar_params_arr.ajx_cleaned_params.calendar__view__cell_height + ' !important;'
189 + '}'
190 +'</style>' );
191 }
192
193 // Define showing mouse over tooltip on unavailable dates
194 jCalContainer.find( '.season_unavailable,.before_after_unavailable,.weekdays_unavailable' ).on( 'mouseover', function ( this_event ){
195 // also available these vars: resource_id, jCalContainer, inst
196 var jCell = jQuery( this_event.currentTarget );
197 wpbc_avy__show_tooltip__for_element( jCell, calendar_params_arr[ 'ajx_data_arr' ]['popover_hints'] );
198 });
199 } );
200
201 //------------------------------------------------------------------------------------------------------------------
202 // Define width of entire calendar
203 var width = 'width:' + calendar_params_arr.ajx_cleaned_params.calendar__view__width + ';'; // var width = 'width:100%;max-width:100%;';
204
205 if ( ( undefined != calendar_params_arr.ajx_cleaned_params.calendar__view__max_width )
206 && ( '' != calendar_params_arr.ajx_cleaned_params.calendar__view__max_width )
207 ){
208 width += 'max-width:' + calendar_params_arr.ajx_cleaned_params.calendar__view__max_width + ';';
209 } else {
210 width += 'max-width:' + ( calendar_params_arr.ajx_cleaned_params.calendar__view__months_in_row * 341 ) + 'px;';
211 }
212
213 //------------------------------------------------------------------------------------------------------------------
214 // Add calendar container: "Calendar is loading..." and textarea
215 jQuery( '.wpbc_ajx_avy__calendar' ).html(
216
217 '<div class="' + ' bk_calendar_frame'
218 + ' months_num_in_row_' + calendar_params_arr.ajx_cleaned_params.calendar__view__months_in_row
219 + ' cal_month_num_' + calendar_params_arr.ajx_cleaned_params.calendar__view__visible_months
220 + '" '
221 + 'style="' + width + '">'
222
223 + '<div id="calendar_booking' + calendar_params_arr.resource_id + '">' + 'Calendar is loading...' + '</div>'
224
225 + '</div>'
226
227 + '<textarea id="date_booking' + calendar_params_arr.resource_id + '"'
228 + ' name="date_booking' + calendar_params_arr.resource_id + '"'
229 + ' autocomplete="off"'
230 + ' style="display:none;width:100%;height:10em;margin:2em 0 0;"></textarea>'
231 );
232
233 //------------------------------------------------------------------------------------------------------------------
234 var cal_param_arr = {
235 'html_id' : 'calendar_booking' + calendar_params_arr.ajx_cleaned_params.resource_id,
236 'text_id' : 'date_booking' + calendar_params_arr.ajx_cleaned_params.resource_id,
237
238 'calendar__start_week_day': calendar_params_arr.ajx_cleaned_params.calendar__start_week_day,
239 'calendar__view__visible_months': calendar_params_arr.ajx_cleaned_params.calendar__view__visible_months,
240 'calendar__days_selection_mode': calendar_params_arr.ajx_cleaned_params.calendar__days_selection_mode,
241
242 'resource_id' : calendar_params_arr.ajx_cleaned_params.resource_id,
243 'ajx_nonce_calendar' : calendar_params_arr.ajx_data_arr.ajx_nonce_calendar,
244 'booked_dates' : calendar_params_arr.ajx_data_arr.booked_dates,
245 'season_availability': calendar_params_arr.ajx_data_arr.season_availability,
246
247 'resource_unavailable_dates' : calendar_params_arr.ajx_data_arr.resource_unavailable_dates,
248
249 'popover_hints': calendar_params_arr[ 'ajx_data_arr' ]['popover_hints'] // {'season_unavailable':'...','weekdays_unavailable':'...','before_after_unavailable':'...',}
250 };
251 wpbc_show_inline_booking_calendar( cal_param_arr );
252
253 //------------------------------------------------------------------------------------------------------------------
254 /**
255 * On click AVAILABLE | UNAVAILABLE button in widget - need to change help dates text
256 */
257 jQuery( '.wpbc_radio__set_days_availability' ).on('change', function ( event, resource_id, inst ){
258 wpbc__inline_booking_calendar__on_days_select( jQuery( '#' + cal_param_arr.text_id ).val() , cal_param_arr );
259 });
260
261 // Show 'Select days in calendar then select Available / Unavailable status and click Apply availability button.'
262 jQuery( '#wpbc_toolbar_dates_hint').html( '<div class="ui_element"><span class="wpbc_ui_control wpbc_ui_addon wpbc_help_text" >'
263 + cal_param_arr.popover_hints.toolbar_text
264 + '</span></div>'
265 );
266 }
267
268
269 /**
270 * Load Datepick Inline calendar
271 *
272 * @param calendar_params_arr example:{
273 'html_id' : 'calendar_booking' + calendar_params_arr.ajx_cleaned_params.resource_id,
274 'text_id' : 'date_booking' + calendar_params_arr.ajx_cleaned_params.resource_id,
275
276 'calendar__start_week_day': calendar_params_arr.ajx_cleaned_params.calendar__start_week_day,
277 'calendar__view__visible_months': calendar_params_arr.ajx_cleaned_params.calendar__view__visible_months,
278 'calendar__days_selection_mode': calendar_params_arr.ajx_cleaned_params.calendar__days_selection_mode,
279
280 'resource_id' : calendar_params_arr.ajx_cleaned_params.resource_id,
281 'ajx_nonce_calendar' : calendar_params_arr.ajx_data_arr.ajx_nonce_calendar,
282 'booked_dates' : calendar_params_arr.ajx_data_arr.booked_dates,
283 'season_availability': calendar_params_arr.ajx_data_arr.season_availability,
284
285 'resource_unavailable_dates' : calendar_params_arr.ajx_data_arr.resource_unavailable_dates
286 }
287 * @returns {boolean}
288 */
289 function wpbc_show_inline_booking_calendar( calendar_params_arr ){
290
291 if (
292 ( 0 === jQuery( '#' + calendar_params_arr.html_id ).length ) // If calendar DOM element not exist then exist
293 || ( true === jQuery( '#' + calendar_params_arr.html_id ).hasClass( 'hasDatepick' ) ) // If the calendar with the same Booking resource already has been activated, then exist.
294 ){
295 return false;
296 }
297
298 //------------------------------------------------------------------------------------------------------------------
299 // Configure and show calendar
300 jQuery( '#' + calendar_params_arr.html_id ).text( '' );
301 jQuery( '#' + calendar_params_arr.html_id ).datepick({
302 beforeShowDay: function ( date ){
303 return wpbc__inline_booking_calendar__apply_css_to_days( date, calendar_params_arr, this );
304 },
305 onSelect: function ( date ){
306 jQuery( '#' + calendar_params_arr.text_id ).val( date );
307 //wpbc_blink_element('.wpbc_widget_available_unavailable', 3, 220);
308 return wpbc__inline_booking_calendar__on_days_select( date, calendar_params_arr, this );
309 },
310 onHover: function ( value, date ){
311
312 //wpbc_avy__prepare_tooltip__in_calendar( value, date, calendar_params_arr, this );
313
314 return wpbc__inline_booking_calendar__on_days_hover( value, date, calendar_params_arr, this );
315 },
316 onChangeMonthYear: null,
317 showOn: 'both',
318 numberOfMonths: calendar_params_arr.calendar__view__visible_months,
319 stepMonths: 1,
320 // prevText: '&laquo;',
321 // nextText: '&raquo;',
322 prevText : '&lsaquo;',
323 nextText : '&rsaquo;',
324 dateFormat: 'yy-mm-dd',// 'dd.mm.yy',
325 changeMonth: false,
326 changeYear: false,
327 minDate: 0, //null, //Scroll as long as you need
328 maxDate: '10y', // minDate: new Date(2020, 2, 1), maxDate: new Date(2020, 9, 31), // Ability to set any start and end date in calendar
329 showStatus: false,
330 closeAtTop: false,
331 firstDay: calendar_params_arr.calendar__start_week_day,
332 gotoCurrent: false,
333 hideIfNoPrevNext: true,
334 multiSeparator: ', ',
335 multiSelect: (('dynamic' == calendar_params_arr.calendar__days_selection_mode) ? 0 : 365), // Maximum number of selectable dates: Single day = 0, multi days = 365
336 rangeSelect: ('dynamic' == calendar_params_arr.calendar__days_selection_mode),
337 rangeSeparator: ' ~ ', //' - ',
338 // showWeeks: true,
339 useThemeRoller: false
340 }
341 );
342
343 return true;
344 }
345
346
347 /**
348 * Apply CSS to calendar date cells
349 *
350 * @param date - JavaScript Date Obj: Mon Dec 11 2023 00:00:00 GMT+0200 (Eastern European Standard Time)
351 * @param calendar_params_arr - Calendar Settings Object: {
352 "html_id": "calendar_booking4",
353 "text_id": "date_booking4",
354 "calendar__start_week_day": 1,
355 "calendar__view__visible_months": 12,
356 "resource_id": 4,
357 "ajx_nonce_calendar": "<input type=\"hidden\" ... />",
358 "booked_dates": {
359 "12-28-2022": [
360 {
361 "booking_date": "2022-12-28 00:00:00",
362 "approved": "1",
363 "booking_id": "26"
364 }
365 ], ...
366 }
367 'season_availability':{
368 "2023-01-09": true,
369 "2023-01-10": true,
370 "2023-01-11": true, ...
371 }
372 }
373 }
374 * @param datepick_this - this of datepick Obj
375 *
376 * @returns [boolean,string] - [ {true -available | false - unavailable}, 'CSS classes for calendar day cell' ]
377 */
378 function wpbc__inline_booking_calendar__apply_css_to_days( date, calendar_params_arr, datepick_this ){
379
380 var today_date = new Date( _wpbc.get_other_param( 'today_arr' )[ 0 ], (parseInt( _wpbc.get_other_param( 'today_arr' )[ 1 ] ) - 1), _wpbc.get_other_param( 'today_arr' )[ 2 ], 0, 0, 0 );
381 var real_today_date = new Date( _wpbc.get_other_param( 'time_local_arr' )[ 0 ], (parseInt( _wpbc.get_other_param( 'time_local_arr' )[ 1 ] ) - 1), _wpbc.get_other_param( 'time_local_arr' )[ 2 ], 0, 0, 0 );
382
383 var class_day = ( date.getMonth() + 1 ) + '-' + date.getDate() + '-' + date.getFullYear(); // '1-9-2023'
384 var sql_class_day = wpbc__get__sql_class_date( date ); // '2023-01-09'
385
386 var css_date__standard = 'cal4date-' + class_day;
387 var css_date__additional = ' wpbc_weekday_' + date.getDay() + ' ';
388
389 //--------------------------------------------------------------------------------------------------------------
390
391 // WEEKDAYS :: Set unavailable week days from - Settings General page in "Availability" section
392 for ( var i = 0; i < _wpbc.get_other_param( 'availability__week_days_unavailable' ).length; i++ ){
393 if ( date.getDay() == _wpbc.get_other_param( 'availability__week_days_unavailable' )[ i ] ) {
394 return [ !!false, css_date__standard + ' date_user_unavailable' + ' weekdays_unavailable' ];
395 }
396 }
397 // 10.9.6.3.
398 var date_midnight = new Date( parseInt( date.getFullYear() ), (parseInt( date.getMonth() ) - 0), parseInt( date.getDate() ), 0, 0, 0 );
399 // BEFORE_AFTER :: Set unavailable days Before / After the Today date.
400 //if ( ((wpbc_dates__days_between( date, real_today_date )) < parseInt( _wpbc.get_other_param( 'availability__unavailable_from_today' ) ))
401 if (
402 ( (today_date.getTime() - date_midnight.getTime() ) > 0 )
403 || (
404 (parseInt( '0' + parseInt( _wpbc.get_other_param( 'availability__available_from_today' ) ) ) > 0)
405 && (wpbc_dates__days_between( date_midnight, real_today_date ) >= parseInt( '0' + parseInt( _wpbc.get_other_param( 'availability__available_from_today' ) ) ))
406 )
407 ) {
408 return [ false, css_date__standard + ' date_user_unavailable' + ' before_after_unavailable' ];
409 }
410
411 // SEASONS :: Booking > Resources > Availability page
412 var is_date_available = calendar_params_arr.season_availability[ sql_class_day ];
413 if ( false === is_date_available ){ // FixIn: 9.5.4.4.
414 return [ !!false, css_date__standard + ' date_user_unavailable' + ' season_unavailable' ];
415 }
416
417 // RESOURCE_UNAVAILABLE :: Booking > Availability page
418 if ( wpbc_in_array(calendar_params_arr.resource_unavailable_dates, sql_class_day ) ){
419 is_date_available = false;
420 }
421 if ( false === is_date_available ){ // FixIn: 9.5.4.4.
422 return [ !false, css_date__standard + ' date_user_unavailable' + ' resource_unavailable' ];
423 }
424
425 //--------------------------------------------------------------------------------------------------------------
426
427 //--------------------------------------------------------------------------------------------------------------
428
429
430 // Is any bookings in this date ?
431 if ( 'undefined' !== typeof( calendar_params_arr.booked_dates[ class_day ] ) ) {
432
433 var bookings_in_date = calendar_params_arr.booked_dates[ class_day ];
434
435
436 if ( 'undefined' !== typeof( bookings_in_date[ 'sec_0' ] ) ) { // "Full day" booking -> (seconds == 0)
437
438 css_date__additional += ( '0' === bookings_in_date[ 'sec_0' ].approved ) ? ' date2approve ' : ' date_approved '; // Pending = '0' | Approved = '1'
439 css_date__additional += ' full_day_booking';
440
441 return [ !false, css_date__standard + css_date__additional ];
442
443 } else if ( Object.keys( bookings_in_date ).length > 0 ){ // "Time slots" Bookings
444
445 var is_approved = true;
446
447 _.each( bookings_in_date, function ( p_val, p_key, p_data ) {
448 if ( !parseInt( p_val.approved ) ){
449 is_approved = false;
450 }
451 var ts = p_val.booking_date.substring( p_val.booking_date.length - 1 );
452 if ( true === _wpbc.get_other_param( 'is_enabled_change_over' ) ){
453 if ( ts == '1' ) { css_date__additional += ' check_in_time' + ((parseInt(p_val.approved)) ? ' check_in_time_date_approved' : ' check_in_time_date2approve'); }
454 if ( ts == '2' ) { css_date__additional += ' check_out_time' + ((parseInt(p_val.approved)) ? ' check_out_time_date_approved' : ' check_out_time_date2approve'); }
455 }
456
457 });
458
459 if ( ! is_approved ){
460 css_date__additional += ' date2approve timespartly'
461 } else {
462 css_date__additional += ' date_approved timespartly'
463 }
464
465 if ( ! _wpbc.get_other_param( 'is_enabled_change_over' ) ){
466 css_date__additional += ' times_clock'
467 }
468
469 }
470
471 }
472
473 //--------------------------------------------------------------------------------------------------------------
474
475 return [ true, css_date__standard + css_date__additional + ' date_available' ];
476 }
477
478
479 /**
480 * Apply some CSS classes, when we mouse over specific dates in calendar
481 * @param value
482 * @param date - JavaScript Date Obj: Mon Dec 11 2023 00:00:00 GMT+0200 (Eastern European Standard Time)
483 * @param calendar_params_arr - Calendar Settings Object: {
484 "html_id": "calendar_booking4",
485 "text_id": "date_booking4",
486 "calendar__start_week_day": 1,
487 "calendar__view__visible_months": 12,
488 "resource_id": 4,
489 "ajx_nonce_calendar": "<input type=\"hidden\" ... />",
490 "booked_dates": {
491 "12-28-2022": [
492 {
493 "booking_date": "2022-12-28 00:00:00",
494 "approved": "1",
495 "booking_id": "26"
496 }
497 ], ...
498 }
499 'season_availability':{
500 "2023-01-09": true,
501 "2023-01-10": true,
502 "2023-01-11": true, ...
503 }
504 }
505 }
506 * @param datepick_this - this of datepick Obj
507 *
508 * @returns {boolean}
509 */
510 function wpbc__inline_booking_calendar__on_days_hover( value, date, calendar_params_arr, datepick_this ){
511
512 if ( null === date ){
513 jQuery( '.datepick-days-cell-over' ).removeClass( 'datepick-days-cell-over' ); // clear all highlight days selections
514 return false;
515 }
516
517 var inst = jQuery.datepick._getInst( document.getElementById( 'calendar_booking' + calendar_params_arr.resource_id ) );
518
519 if (
520 ( 1 == inst.dates.length) // If we have one selected date
521 && ('dynamic' === calendar_params_arr.calendar__days_selection_mode) // while have range days selection mode
522 ){
523
524 var td_class;
525 var td_overs = [];
526 var is_check = true;
527 var selceted_first_day = new Date();
528 selceted_first_day.setFullYear(inst.dates[0].getFullYear(),(inst.dates[0].getMonth()), (inst.dates[0].getDate() ) ); //Get first Date
529
530 while( is_check ){
531
532 td_class = (selceted_first_day.getMonth() + 1) + '-' + selceted_first_day.getDate() + '-' + selceted_first_day.getFullYear();
533
534 td_overs[ td_overs.length ] = '#calendar_booking' + calendar_params_arr.resource_id + ' .cal4date-' + td_class; // add to array for later make selection by class
535
536 if (
537 ( ( date.getMonth() == selceted_first_day.getMonth() ) &&
538 ( date.getDate() == selceted_first_day.getDate() ) &&
539 ( date.getFullYear() == selceted_first_day.getFullYear() )
540 ) || ( selceted_first_day > date )
541 ){
542 is_check = false;
543 }
544
545 selceted_first_day.setFullYear( selceted_first_day.getFullYear(), (selceted_first_day.getMonth()), (selceted_first_day.getDate() + 1) );
546 }
547
548 // Highlight Days
549 for ( var i=0; i < td_overs.length ; i++) { // add class to all elements
550 jQuery( td_overs[i] ).addClass('datepick-days-cell-over');
551 }
552 return true;
553
554 }
555
556 return true;
557 }
558
559
560 /**
561 * On DAYs selection in calendar
562 *
563 * @param dates_selection - string: '2023-03-07 ~ 2023-03-07' or '2023-04-10, 2023-04-12, 2023-04-02, 2023-04-04'
564 * @param calendar_params_arr - Calendar Settings Object: {
565 "html_id": "calendar_booking4",
566 "text_id": "date_booking4",
567 "calendar__start_week_day": 1,
568 "calendar__view__visible_months": 12,
569 "resource_id": 4,
570 "ajx_nonce_calendar": "<input type=\"hidden\" ... />",
571 "booked_dates": {
572 "12-28-2022": [
573 {
574 "booking_date": "2022-12-28 00:00:00",
575 "approved": "1",
576 "booking_id": "26"
577 }
578 ], ...
579 }
580 'season_availability':{
581 "2023-01-09": true,
582 "2023-01-10": true,
583 "2023-01-11": true, ...
584 }
585 }
586 }
587 * @param datepick_this - this of datepick Obj
588 *
589 * @returns boolean
590 */
591 function wpbc__inline_booking_calendar__on_days_select( dates_selection, calendar_params_arr, datepick_this = null ){
592
593 var inst = jQuery.datepick._getInst( document.getElementById( 'calendar_booking' + calendar_params_arr.resource_id ) );
594
595 var dates_arr = []; // [ "2023-04-09", "2023-04-10", "2023-04-11" ]
596
597 if ( -1 !== dates_selection.indexOf( '~' ) ) { // Range Days
598
599 dates_arr = wpbc_get_dates_arr__from_dates_range_js( {
600 'dates_separator' : ' ~ ', // ' ~ '
601 'dates' : dates_selection, // '2023-04-04 ~ 2023-04-07'
602 } );
603
604 } else { // Multiple Days
605 dates_arr = wpbc_get_dates_arr__from_dates_comma_separated_js( {
606 'dates_separator' : ', ', // ', '
607 'dates' : dates_selection, // '2023-04-10, 2023-04-12, 2023-04-02, 2023-04-04'
608 } );
609 }
610
611 wpbc_avy_after_days_selection__show_help_info({
612 'calendar__days_selection_mode': calendar_params_arr.calendar__days_selection_mode,
613 'dates_arr' : dates_arr,
614 'dates_click_num' : inst.dates.length,
615 'popover_hints' : calendar_params_arr.popover_hints
616 } );
617 return true;
618 }
619
620 /**
621 * Show help info at the top toolbar about selected dates and future actions
622 *
623 * @param params
624 * Example 1: {
625 calendar__days_selection_mode: "dynamic",
626 dates_arr: [ "2023-04-03" ],
627 dates_click_num: 1
628 'popover_hints' : calendar_params_arr.popover_hints
629 }
630 * Example 2: {
631 calendar__days_selection_mode: "dynamic"
632 dates_arr: Array(10) [ "2023-04-03", "2023-04-04", "2023-04-05", … ]
633 dates_click_num: 2
634 'popover_hints' : calendar_params_arr.popover_hints
635 }
636 */
637 function wpbc_avy_after_days_selection__show_help_info( params ){
638 // console.log( params ); // [ "2023-04-09", "2023-04-10", "2023-04-11" ]
639
640 var message, color;
641 if (jQuery( '#ui_btn_avy__set_days_availability__available').is(':checked')){
642 message = params.popover_hints.toolbar_text_available;//'Set dates _DATES_ as _HTML_ available.';
643 color = '#11be4c';
644 } else {
645 message = params.popover_hints.toolbar_text_unavailable;//'Set dates _DATES_ as _HTML_ unavailable.';
646 color = '#e43939';
647 }
648
649 message = '<span>' + message + '</span>';
650
651 var first_date = params[ 'dates_arr' ][ 0 ];
652 var last_date = ( 'dynamic' == params.calendar__days_selection_mode )
653 ? params[ 'dates_arr' ][ (params[ 'dates_arr' ].length - 1) ]
654 : ( params[ 'dates_arr' ].length > 1 ) ? params[ 'dates_arr' ][ 1 ] : '';
655
656 first_date = jQuery.datepick.formatDate( 'dd M, yy', new Date( first_date + 'T00:00:00' ) );
657 last_date = jQuery.datepick.formatDate( 'dd M, yy', new Date( last_date + 'T00:00:00' ) );
658
659
660 if ( 'dynamic' == params.calendar__days_selection_mode ){
661 if ( 1 == params.dates_click_num ){
662 last_date = '___________'
663 } else {
664 if ( 'first_time' == jQuery( '.wpbc_ajx_availability_container' ).attr( 'wpbc_loaded' ) ){
665 jQuery( '.wpbc_ajx_availability_container' ).attr( 'wpbc_loaded', 'done' )
666 wpbc_blink_element( '.wpbc_widget_available_unavailable', 3, 220 );
667 }
668 }
669 message = message.replace( '_DATES_', '</span>'
670 //+ '<div>' + 'from' + '</div>'
671 + '<span class="wpbc_big_date">' + first_date + '</span>'
672 + '<span>' + '-' + '</span>'
673 + '<span class="wpbc_big_date">' + last_date + '</span>'
674 + '<span>' );
675 } else {
676 // if ( params[ 'dates_arr' ].length > 1 ){
677 // last_date = ', ' + last_date;
678 // last_date += ( params[ 'dates_arr' ].length > 2 ) ? ', ...' : '';
679 // } else {
680 // last_date='';
681 // }
682 var dates_arr = [];
683 for( var i = 0; i < params[ 'dates_arr' ].length; i++ ){
684 dates_arr.push( jQuery.datepick.formatDate( 'dd M yy', new Date( params[ 'dates_arr' ][ i ] + 'T00:00:00' ) ) );
685 }
686 first_date = dates_arr.join( ', ' );
687 message = message.replace( '_DATES_', '</span>'
688 + '<span class="wpbc_big_date">' + first_date + '</span>'
689 + '<span>' );
690 }
691 message = message.replace( '_HTML_' , '</span><span class="wpbc_big_text" style="color:'+color+';">') + '<span>';
692
693 //message += ' <div style="margin-left: 1em;">' + ' Click on Apply button to apply availability.' + '</div>';
694
695 message = '<div class="wpbc_toolbar_dates_hints">' + message + '</div>';
696
697 jQuery( '.wpbc_help_text' ).html( message );
698 }
699
700 /**
701 * Parse dates ------------------------------------------------------------------------------------------- */
702
703 /**
704 * Get dates array, from comma separated dates
705 *
706 * @param params = {
707 * 'dates_separator' => ', ', // Dates separator
708 * 'dates' => '2023-04-04, 2023-04-07, 2023-04-05' // Dates in 'Y-m-d' format: '2023-01-31'
709 }
710 *
711 * @return array = [
712 * [0] => 2023-04-04
713 * [1] => 2023-04-05
714 * [2] => 2023-04-06
715 * [3] => 2023-04-07
716 ]
717 *
718 * Example #1: wpbc_get_dates_arr__from_dates_comma_separated_js( { 'dates_separator' : ', ', 'dates' : '2023-04-04, 2023-04-07, 2023-04-05' } );
719 */
720 function wpbc_get_dates_arr__from_dates_comma_separated_js( params ){
721
722 var dates_arr = [];
723
724 if ( '' !== params[ 'dates' ] ){
725
726 dates_arr = params[ 'dates' ].split( params[ 'dates_separator' ] );
727
728 dates_arr.sort();
729 }
730 return dates_arr;
731 }
732
733 /**
734 * Get dates array, from range days selection
735 *
736 * @param params = {
737 * 'dates_separator' => ' ~ ', // Dates separator
738 * 'dates' => '2023-04-04 ~ 2023-04-07' // Dates in 'Y-m-d' format: '2023-01-31'
739 }
740 *
741 * @return array = [
742 * [0] => 2023-04-04
743 * [1] => 2023-04-05
744 * [2] => 2023-04-06
745 * [3] => 2023-04-07
746 ]
747 *
748 * Example #1: wpbc_get_dates_arr__from_dates_range_js( { 'dates_separator' : ' ~ ', 'dates' : '2023-04-04 ~ 2023-04-07' } );
749 * Example #2: wpbc_get_dates_arr__from_dates_range_js( { 'dates_separator' : ' - ', 'dates' : '2023-04-04 - 2023-04-07' } );
750 */
751 function wpbc_get_dates_arr__from_dates_range_js( params ){
752
753 var dates_arr = [];
754
755 if ( '' !== params['dates'] ) {
756
757 dates_arr = params[ 'dates' ].split( params[ 'dates_separator' ] );
758 var check_in_date_ymd = dates_arr[0];
759 var check_out_date_ymd = dates_arr[1];
760
761 if ( ('' !== check_in_date_ymd) && ('' !== check_out_date_ymd) ){
762
763 dates_arr = wpbc_get_dates_array_from_start_end_days_js( check_in_date_ymd, check_out_date_ymd );
764 }
765 }
766 return dates_arr;
767 }
768
769 /**
770 * Get dates array based on start and end dates.
771 *
772 * @param string sStartDate - start date: 2023-04-09
773 * @param string sEndDate - end date: 2023-04-11
774 * @return array - [ "2023-04-09", "2023-04-10", "2023-04-11" ]
775 */
776 function wpbc_get_dates_array_from_start_end_days_js( sStartDate, sEndDate ){
777
778 sStartDate = new Date( sStartDate + 'T00:00:00' );
779 sEndDate = new Date( sEndDate + 'T00:00:00' );
780
781 var aDays=[];
782
783 // Start the variable off with the start date
784 aDays.push( sStartDate.getTime() );
785
786 // Set a 'temp' variable, sCurrentDate, with the start date - before beginning the loop
787 var sCurrentDate = new Date( sStartDate.getTime() );
788 var one_day_duration = 24*60*60*1000;
789
790 // While the current date is less than the end date
791 while(sCurrentDate < sEndDate){
792 // Add a day to the current date "+1 day"
793 sCurrentDate.setTime( sCurrentDate.getTime() + one_day_duration );
794
795 // Add this new day to the aDays array
796 aDays.push( sCurrentDate.getTime() );
797 }
798
799 for (let i = 0; i < aDays.length; i++) {
800 aDays[ i ] = new Date( aDays[i] );
801 aDays[ i ] = aDays[ i ].getFullYear()
802 + '-' + (( (aDays[ i ].getMonth() + 1) < 10) ? '0' : '') + (aDays[ i ].getMonth() + 1)
803 + '-' + (( aDays[ i ].getDate() < 10) ? '0' : '') + aDays[ i ].getDate();
804 }
805 // Once the loop has finished, return the array of days.
806 return aDays;
807 }
808
809
810
811 /**
812 * Tooltips ---------------------------------------------------------------------------------------------- */
813
814 /**
815 * Define showing tooltip, when mouse over on SELECTABLE (available, pending, approved, resource unavailable), days
816 * Can be called directly from datepick init function.
817 *
818 * @param value
819 * @param date
820 * @param calendar_params_arr
821 * @param datepick_this
822 * @returns {boolean}
823 */
824 function wpbc_avy__prepare_tooltip__in_calendar( value, date, calendar_params_arr, datepick_this ){
825
826 if ( null == date ){ return false; }
827
828 var td_class = ( date.getMonth() + 1 ) + '-' + date.getDate() + '-' + date.getFullYear();
829
830 var jCell = jQuery( '#calendar_booking' + calendar_params_arr.resource_id + ' td.cal4date-' + td_class );
831
832 wpbc_avy__show_tooltip__for_element( jCell, calendar_params_arr[ 'popover_hints' ] );
833 return true;
834 }
835
836
837 /**
838 * Define tooltip for showing on UNAVAILABLE days (season, weekday, today_depends unavailable)
839 *
840 * @param jCell jQuery of specific day cell
841 * @param popover_hints Array with tooltip hint texts : {'season_unavailable':'...','weekdays_unavailable':'...','before_after_unavailable':'...',}
842 */
843 function wpbc_avy__show_tooltip__for_element( jCell, popover_hints ){
844
845 var tooltip_time = '';
846
847 if ( jCell.hasClass( 'season_unavailable' ) ){
848 tooltip_time = popover_hints[ 'season_unavailable' ];
849 } else if ( jCell.hasClass( 'weekdays_unavailable' ) ){
850 tooltip_time = popover_hints[ 'weekdays_unavailable' ];
851 } else if ( jCell.hasClass( 'before_after_unavailable' ) ){
852 tooltip_time = popover_hints[ 'before_after_unavailable' ];
853 } else if ( jCell.hasClass( 'date2approve' ) ){
854
855 } else if ( jCell.hasClass( 'date_approved' ) ){
856
857 } else {
858
859 }
860
861 jCell.attr( 'data-content', tooltip_time );
862
863 var td_el = jCell.get(0); //jQuery( '#calendar_booking' + calendar_params_arr.resource_id + ' td.cal4date-' + td_class ).get(0);
864
865 if ( ( undefined == td_el._tippy ) && ( '' != tooltip_time ) ){
866
867 wpbc_tippy( td_el , {
868 content( reference ){
869
870 var popover_content = reference.getAttribute( 'data-content' );
871
872 return '<div class="popover popover_tippy">'
873 + '<div class="popover-content">'
874 + popover_content
875 + '</div>'
876 + '</div>';
877 },
878 allowHTML : true,
879 trigger : 'mouseenter focus',
880 interactive : ! true,
881 hideOnClick : true,
882 interactiveBorder: 10,
883 maxWidth : 550,
884 theme : 'wpbc-tippy-times',
885 placement : 'top',
886 delay : [400, 0], // FixIn: 9.4.2.2.
887 ignoreAttributes : true,
888 touch : true, //['hold', 500], // 500ms delay // FixIn: 9.2.1.5.
889 appendTo: () => document.body,
890 });
891 }
892 }
893
894
895
896
897
898 /**
899 * Ajax ------------------------------------------------------------------------------------------------------ */
900
901 /**
902 * Send Ajax show request
903 */
904 function wpbc_ajx_availability__ajax_request(){
905
906 console.groupCollapsed( 'WPBC_AJX_AVAILABILITY' ); console.log( ' == Before Ajax Send - search_get_all_params() == ' , wpbc_ajx_availability.search_get_all_params() );
907
908 wpbc_availability_reload_button__spin_start();
909
910 // Start Ajax
911 jQuery.post( wpbc_url_ajax,
912 {
913 action : 'WPBC_AJX_AVAILABILITY',
914 wpbc_ajx_user_id: wpbc_ajx_availability.get_secure_param( 'user_id' ),
915 nonce : wpbc_ajx_availability.get_secure_param( 'nonce' ),
916 wpbc_ajx_locale : wpbc_ajx_availability.get_secure_param( 'locale' ),
917
918 search_params : wpbc_ajx_availability.search_get_all_params()
919 },
920 /**
921 * S u c c e s s
922 *
923 * @param response_data - its object returned from Ajax - class-live-searcg.php
924 * @param textStatus - 'success'
925 * @param jqXHR - Object
926 */
927 function ( response_data, textStatus, jqXHR ) {
928
929 console.log( ' == Response WPBC_AJX_AVAILABILITY == ', response_data ); console.groupEnd();
930
931 // Probably Error
932 if ( (typeof response_data !== 'object') || (response_data === null) ){
933
934 wpbc_ajx_availability__show_message( response_data );
935
936 return;
937 }
938
939 // Reload page, after filter toolbar has been reset
940 if ( ( undefined != response_data[ 'ajx_cleaned_params' ])
941 && ( 'reset_done' === response_data[ 'ajx_cleaned_params' ][ 'do_action' ])
942 ){
943 location.reload();
944 return;
945 }
946
947 // Show listing
948 wpbc_ajx_availability__page_content__show( response_data[ 'ajx_data' ], response_data[ 'ajx_search_params' ] , response_data[ 'ajx_cleaned_params' ] );
949
950 //wpbc_ajx_availability__define_ui_hooks(); // Redefine Hooks, because we show new DOM elements
951 if ( '' != response_data[ 'ajx_data' ][ 'ajx_after_action_message' ].replace( /\n/g, "<br />" ) ){
952 wpbc_admin_show_message(
953 response_data[ 'ajx_data' ][ 'ajx_after_action_message' ].replace( /\n/g, "<br />" )
954 , ( '1' == response_data[ 'ajx_data' ][ 'ajx_after_action_result' ] ) ? 'success' : 'error'
955 , 10000
956 );
957 }
958
959 wpbc_availability_reload_button__spin_pause();
960 // Remove spin icon from button and Enable this button.
961 wpbc_button__remove_spin( response_data[ 'ajx_cleaned_params' ][ 'ui_clicked_element_id' ] )
962
963 jQuery( '#ajax_respond' ).html( response_data ); // For ability to show response, add such DIV element to page
964 }
965 ).fail( function ( jqXHR, textStatus, errorThrown ) { if ( window.console && window.console.log ){ console.log( 'Ajax_Error', jqXHR, textStatus, errorThrown ); }
966
967 var error_message = '<strong>' + 'Error!' + '</strong> ' + errorThrown ;
968 if ( jqXHR.status ){
969 error_message += ' (<b>' + jqXHR.status + '</b>)';
970 if (403 == jqXHR.status ){
971 error_message += ' Probably nonce for this page has been expired. Please <a href="javascript:void(0)" onclick="javascript:location.reload();">reload the page</a>.';
972 }
973 }
974 if ( jqXHR.responseText ){
975 error_message += ' ' + jqXHR.responseText;
976 }
977 error_message = error_message.replace( /\n/g, "<br />" );
978
979 wpbc_ajx_availability__show_message( error_message );
980 })
981 // .done( function ( data, textStatus, jqXHR ) { if ( window.console && window.console.log ){ console.log( 'second success', data, textStatus, jqXHR ); } })
982 // .always( function ( data_jqXHR, textStatus, jqXHR_errorThrown ) { if ( window.console && window.console.log ){ console.log( 'always finished', data_jqXHR, textStatus, jqXHR_errorThrown ); } })
983 ; // End Ajax
984
985 }
986
987
988
989 /**
990 * H o o k s - its Action/Times when need to re-Render Views ----------------------------------------------- */
991
992 /**
993 * Send Ajax Search Request after Updating search request parameters
994 *
995 * @param params_arr
996 */
997 function wpbc_ajx_availability__send_request_with_params ( params_arr ){
998
999 // Define different Search parameters for request
1000 _.each( params_arr, function ( p_val, p_key, p_data ) {
1001 //console.log( 'Request for: ', p_key, p_val );
1002 wpbc_ajx_availability.search_set_param( p_key, p_val );
1003 });
1004
1005 // Send Ajax Request
1006 wpbc_ajx_availability__ajax_request();
1007 }
1008
1009
1010 /**
1011 * Search request for "Page Number"
1012 * @param page_number int
1013 */
1014 function wpbc_ajx_availability__pagination_click( page_number ){
1015
1016 wpbc_ajx_availability__send_request_with_params( {
1017 'page_num': page_number
1018 } );
1019 }
1020
1021
1022
1023 /**
1024 * Show / Hide Content --------------------------------------------------------------------------------------- */
1025
1026 /**
1027 * Show Listing Content - Sending Ajax Request - with parameters that we early defined
1028 */
1029 function wpbc_ajx_availability__actual_content__show(){
1030
1031 wpbc_ajx_availability__ajax_request(); // Send Ajax Request - with parameters that we early defined in "wpbc_ajx_booking_listing" Obj.
1032 }
1033
1034 /**
1035 * Hide Listing Content
1036 */
1037 function wpbc_ajx_availability__actual_content__hide(){
1038
1039 jQuery( wpbc_ajx_availability.get_other_param( 'listing_container' ) ).html( '' );
1040 }
1041
1042
1043
1044 /**
1045 * M e s s a g e --------------------------------------------------------------------------------------------- */
1046
1047 /**
1048 * Show just message instead of content
1049 */
1050 function wpbc_ajx_availability__show_message( message ){
1051
1052 wpbc_ajx_availability__actual_content__hide();
1053
1054 jQuery( wpbc_ajx_availability.get_other_param( 'listing_container' ) ).html(
1055 '<div class="wpbc-settings-notice notice-warning" style="text-align:left">' +
1056 message +
1057 '</div>'
1058 );
1059 }
1060
1061
1062
1063 /**
1064 * Support Functions - Spin Icon in Buttons ------------------------------------------------------------------ */
1065
1066 /**
1067 * Spin button in Filter toolbar - Start
1068 */
1069 function wpbc_availability_reload_button__spin_start(){
1070 jQuery( '#wpbc_availability_reload_button .menu_icon.wpbc_spin').removeClass( 'wpbc_animation_pause' );
1071 }
1072
1073 /**
1074 * Spin button in Filter toolbar - Pause
1075 */
1076 function wpbc_availability_reload_button__spin_pause(){
1077 jQuery( '#wpbc_availability_reload_button .menu_icon.wpbc_spin' ).addClass( 'wpbc_animation_pause' );
1078 }
1079
1080 /**
1081 * Spin button in Filter toolbar - is Spinning ?
1082 *
1083 * @returns {boolean}
1084 */
1085 function wpbc_availability_reload_button__is_spin(){
1086 if ( jQuery( '#wpbc_availability_reload_button .menu_icon.wpbc_spin' ).hasClass( 'wpbc_animation_pause' ) ){
1087 return true;
1088 } else {
1089 return false;
1090 }
1091 }
1092