PluginProbe
Booking Calendar / 11.9
Booking Calendar v11.9
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
← All changes | includes/__js/client/cal/wpbc_cal.js +167 -53 11.8.4 → 11.9 View file →
@@ -146,10 +146,14 @@
146 146 // -----------------------------------------------------------------------------------------------------------------
147 147 // Show calendar
148 148 // -----------------------------------------------------------------------------------------------------------------
149 149 jQuery('#calendar_booking'+ resource_id).datepick(
150 - {
151 - beforeShowDay: function ( js_date ){
150 + {
151 + beforeSelectDay: function ( js_date, inst ) {
152 + return 'function' === typeof wpbc__calendar__before_select_days__bs
153 + ? wpbc__calendar__before_select_days__bs( js_date, resource_id, inst ) : true;
154 + },
155 + beforeShowDay: function ( js_date ){
152 156 return wpbc__calendar__apply_css_to_days( js_date, {'resource_id': resource_id}, this );
153 157 },
154 158 onSelect: function ( string_dates, js_dates_arr ){ /**
155 159 * string_dates = '23.08.2023 - 26.08.2023'
@@ -267,13 +271,96 @@
267 271 }
268 272 }
269 273
270 274 return false;
271 - }
272 -
273 -
274 - /**
275 - * Apply CSS to calendar date cells
275 + }
276 +
277 +
278 + /**
279 + * Apply optional, one-way date constraints to a native availability result.
280 + *
281 + * Listeners receive only a new constraint object. No booking, availability,
282 + * season, or calendar parameter objects are exposed. Core availability stays
283 + * authoritative because the returned state can only change from selectable to
284 + * blocked; a listener cannot reopen a natively unavailable date.
285 + *
286 + * Event: wpbc_calendar__apply_date_constraints
287 + *
288 + * Constraint object:
289 + * {
290 + * resource_id: resource_id,
291 + * sql_date: sql_date,
292 + * is_blocked: false,
293 + * css_classes: []
294 + * }
295 + *
296 + * Listeners may set is_blocked to the boolean true and append individual,
297 + * valid CSS class names to css_classes. Core-owned availability classes are
298 + * ignored when supplied by listeners.
299 + *
300 + * @param {number|string} resource_id Booking resource ID.
301 + * @param {string} sql_date Calendar date in YYYY-MM-DD format.
302 + * @param {boolean} is_natively_selectable Whether core marked the date selectable.
303 + * @param {string[]} native_css_classes Core-generated CSS classes.
304 + * @returns {{is_selectable: boolean, css_classes: string[]}} Constrained result.
305 + */
306 + function wpbc_calendar__evaluate_date_constraints( resource_id, sql_date, is_natively_selectable, native_css_classes ) {
307 +
308 + var date_constraint = {
309 + 'resource_id': resource_id,
310 + 'sql_date': sql_date,
311 + 'is_blocked': false,
312 + 'css_classes': []
313 + };
314 + var result_css_classes = Array.isArray( native_css_classes ) ? native_css_classes.slice( 0 ) : [];
315 + var constraint_class_index;
316 + var constraint_css_class;
317 +
318 + jQuery( 'body' ).trigger( 'wpbc_calendar__apply_date_constraints', [ date_constraint ] );
319 +
320 + if ( true === date_constraint.is_blocked ) {
321 + for ( constraint_class_index = result_css_classes.length - 1; constraint_class_index >= 0; constraint_class_index-- ) {
322 + if ( 'date_available' === result_css_classes[ constraint_class_index ] ) {
323 + result_css_classes.splice( constraint_class_index, 1 );
324 + }
325 + }
326 +
327 + if ( -1 === result_css_classes.indexOf( 'date_user_unavailable' ) ) {
328 + result_css_classes.push( 'date_user_unavailable' );
329 + }
330 + }
331 +
332 + if ( Array.isArray( date_constraint.css_classes ) ) {
333 + for ( constraint_class_index = 0; constraint_class_index < date_constraint.css_classes.length; constraint_class_index++ ) {
334 + if ( 'string' !== typeof date_constraint.css_classes[ constraint_class_index ] ) {
335 + continue;
336 + }
337 +
338 + constraint_css_class = date_constraint.css_classes[ constraint_class_index ].trim();
339 + if (
340 + '' === constraint_css_class
341 + || 'date_available' === constraint_css_class
342 + || 'date_user_unavailable' === constraint_css_class
343 + || ! /^-?[_a-zA-Z]+[_a-zA-Z0-9-]*$/.test( constraint_css_class )
344 + ) {
345 + continue;
346 + }
347 +
348 + if ( -1 === result_css_classes.indexOf( constraint_css_class ) ) {
349 + result_css_classes.push( constraint_css_class );
350 + }
351 + }
352 + }
353 +
354 + return {
355 + 'is_selectable': Boolean( is_natively_selectable ) && true !== date_constraint.is_blocked,
356 + 'css_classes': result_css_classes
357 + };
358 + }
359 +
360 +
361 + /**
362 + * Apply CSS to calendar date cells
276 363 *
277 364 * @param date - JavaScript Date Obj: Mon Dec 11 2023 00:00:00
278 365 * GMT+0200 (Eastern European Standard Time)
279 366 * @param calendar_params_arr - Calendar Settings Object: {
@@ -318,16 +405,18 @@
318 405 }
319 406 }
320 407
321 408
322 - var is_day_selectable = false;
409 + var is_day_selectable = false;
410 + var date_constraint_result;
323 411
324 412 // If something not defined, then this date closed --------------------------------------------------------------- // FixIn: 10.12.4.6.
325 - if ( (false === date_bookings_obj) || ('undefined' === typeof (date_bookings_obj[resource_id])) ) {
326 -
327 - css_classes__for_date.push( 'date_user_unavailable' );
328 -
329 - return [ is_day_selectable, css_classes__for_date.join(' ') ];
413 + if ( (false === date_bookings_obj) || ('undefined' === typeof (date_bookings_obj[resource_id])) ) {
414 +
415 + css_classes__for_date.push( 'date_user_unavailable' );
416 + date_constraint_result = wpbc_calendar__evaluate_date_constraints( resource_id, sql_class_day, is_day_selectable, css_classes__for_date );
417 +
418 + return [ date_constraint_result.is_selectable, date_constraint_result.css_classes.join( ' ' ) ];
330 419 }
331 420
332 421
333 422 // -----------------------------------------------------------------------------------------------------------------
@@ -483,9 +572,11 @@
483 572 css_classes__for_date.push( 'check_out_time_date_approved', 'check_in_time_date_approved' );
484 573 }
485 574 }
486 575
487 - return [ is_day_selectable, css_classes__for_date.join( ' ' ) ];
576 + date_constraint_result = wpbc_calendar__evaluate_date_constraints( resource_id, sql_class_day, is_day_selectable, css_classes__for_date );
577 +
578 + return [ date_constraint_result.is_selectable, date_constraint_result.css_classes.join( ' ' ) ];
488 579 }
489 580
490 581
491 582 /**
@@ -1570,47 +1661,70 @@
1570 1661 }
1571 1662 return false;
1572 1663 }
1573 1664
1574 - /**
1575 - * Is this date selectable in calendar (mainly it's means AVAILABLE date)
1576 - *
1577 - * @param {int|string} resource_id 1
1578 - * @param {string} sql_class_day '2023-08-11'
1579 - * @returns {boolean} true | false
1580 - */
1581 - function wpbc_is_this_day_selectable( resource_id, sql_class_day ){
1665 + /**
1666 + * Determine native date selectability without optional date constraints.
1667 + *
1668 + * This helper exposes the canonical calendar result for algorithms, such as
1669 + * gap discovery, that must not consume their own derived constraints. It does
1670 + * not trigger wpbc_calendar__apply_date_constraints and must remain free of
1671 + * optional-module state.
1672 + *
1673 + * @param {number|string} resource_id Booking resource ID.
1674 + * @param {string} sql_date Calendar date in YYYY-MM-DD format.
1675 + * @returns {boolean} True when core calendar data marks the date selectable.
1676 + */
1677 + function wpbc_is_this_day_selectable__raw( resource_id, sql_date ){
1678 +
1679 + // Get Data --------------------------------------------------------------------------------------------------------
1680 + var date_bookings_obj = _wpbc.bookings_in_calendar__get_for_date( resource_id, sql_date );
1681 + var is_day_selectable = false;
1682 +
1683 + if ( date_bookings_obj && 'undefined' !== typeof ( date_bookings_obj[ 'day_availability' ] ) ) {
1684 + is_day_selectable = ( parseInt( date_bookings_obj[ 'day_availability' ] ) > 0 );
1685 +
1686 + if ( 'undefined' !== typeof ( date_bookings_obj[ 'summary' ] ) && 'available' != date_bookings_obj[ 'summary']['status_for_day' ] ){
1687 +
1688 + var is_set_pending_days_selectable = _wpbc.calendar__get_param_value( resource_id, 'pending_days_selectable' ); // set pending days selectable // FixIn: 8.6.1.18.
1689 + var booking_statuses_arr = wpbc_get_booking_statuses__as_arr( date_bookings_obj );
1690 +
1691 + if (
1692 + ( wpbc_booking_statuses__has( booking_statuses_arr, 'pending' ) )
1693 + || ( wpbc_booking_statuses__has( booking_statuses_arr, 'pending_pending' ) )
1694 + || ( wpbc_booking_statuses__has( booking_statuses_arr, 'pending_approved' ) )
1695 + || ( wpbc_booking_statuses__has( booking_statuses_arr, 'approved_pending' ) )
1696 + ){
1697 + is_day_selectable = (is_day_selectable) ? true : is_set_pending_days_selectable;
1698 + }
1699 + }
1700 + }
1701 +
1702 + return Boolean( is_day_selectable );
1703 + }
1704 +
1705 + /**
1706 + * Determine final date selectability after native and optional constraints.
1707 + *
1708 + * Native unavailability returns immediately. Optional modules may therefore
1709 + * only block a natively selectable date and can never reopen a core-unavailable
1710 + * date.
1711 + *
1712 + * @param {number|string} resource_id Booking resource ID.
1713 + * @param {string} sql_date Calendar date in YYYY-MM-DD format.
1714 + * @returns {boolean} True when the date remains selectable after constraints.
1715 + */
1716 + function wpbc_is_this_day_selectable( resource_id, sql_date ){
1717 +
1718 + var is_natively_selectable = wpbc_is_this_day_selectable__raw( resource_id, sql_date );
1719 +
1720 + if ( ! is_natively_selectable ) {
1721 + return false;
1722 + }
1723 +
1724 + return wpbc_calendar__evaluate_date_constraints( resource_id, sql_date, is_natively_selectable, [] ).is_selectable;
1725 + }
1582 1726
1583 - // Get Data --------------------------------------------------------------------------------------------------------
1584 - var date_bookings_obj = _wpbc.bookings_in_calendar__get_for_date( resource_id, sql_class_day );
1585 - if ( ! date_bookings_obj || 'undefined' === typeof ( date_bookings_obj[ 'day_availability' ] ) ) {
1586 - return false;
1587 - }
1588 -
1589 - var is_day_selectable = ( parseInt( date_bookings_obj[ 'day_availability' ] ) > 0 );
1590 -
1591 - if ( typeof (date_bookings_obj[ 'summary' ]) === 'undefined' ){
1592 - return is_day_selectable;
1593 - }
1594 -
1595 - if ( 'available' != date_bookings_obj[ 'summary']['status_for_day' ] ){
1596 -
1597 - var is_set_pending_days_selectable = _wpbc.calendar__get_param_value( resource_id, 'pending_days_selectable' ); // set pending days selectable // FixIn: 8.6.1.18.
1598 - var booking_statuses_arr = wpbc_get_booking_statuses__as_arr( date_bookings_obj );
1599 -
1600 - if (
1601 - ( wpbc_booking_statuses__has( booking_statuses_arr, 'pending' ) )
1602 - || ( wpbc_booking_statuses__has( booking_statuses_arr, 'pending_pending' ) )
1603 - || ( wpbc_booking_statuses__has( booking_statuses_arr, 'pending_approved' ) )
1604 - || ( wpbc_booking_statuses__has( booking_statuses_arr, 'approved_pending' ) )
1605 - ){
1606 - is_day_selectable = (is_day_selectable) ? true : is_set_pending_days_selectable;
1607 - }
1608 - }
1609 -
1610 - return is_day_selectable;
1611 - }
1612 -
1613 1727 /**
1614 1728 * Is date to check IN array of selected dates
1615 1729 *
1616 1730 * @param {date}js_date_to_check - JS Date - simple JavaScript Date object
@@ -2268,9 +2382,9 @@
2268 2382 // Scroll to specific month, if we set dates in some future months
2269 2383 wpbc_calendar__scroll_to( resource_id, inst.dates[ 0 ].getFullYear(), inst.dates[ 0 ].getMonth()+1 );
2270 2384 }
2271 2385
2272 - return inst.dates.length;
2386 + return wpbc_get__selected_dates_sql__as_arr( resource_id ).length;
2273 2387 }
2274 2388
2275 2389 return 0;
2276 2390 }