PluginProbe
Booking Calendar / 10.1.3
Booking Calendar v10.1.3
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 10.11.2 All 203 releases
booking / includes / page-availability / _src / availability_page.js

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

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