| @@ -1,4 +1,4 @@ | ||
| 1 | 1 | /** |
| 2 | 2 | * ===================================================================================================================== |
| 3 | 3 | * includes/__js/cal/wpbc_cal.js |
| 4 | 4 | * ===================================================================================================================== |
| @@ -76,9 +76,9 @@ | ||
| 76 | 76 | // Stale marker: remove and continue with init. |
| 77 | 77 | jQuery( '#calendar_booking' + resource_id ).removeClass( 'hasDatepick' ); |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | - wpbc_range_selection__hide_guidance( resource_id ); | |
| 80 | + wpbc_range_selection__prepare_guidance( resource_id ); | |
| 81 | 81 | |
| 82 | 82 | |
| 83 | 83 | |
| 84 | 84 | // ----------------------------------------------------------------------------------------------------------------- |
| @@ -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 | /** |
| @@ -704,33 +795,21 @@ | ||
| 704 | 795 | } |
| 705 | 796 | |
| 706 | 797 | |
| 707 | 798 | /** |
| 708 | - * Remove the range-selection guidance belonging to one calendar. | |
| 799 | + * Prepare a collapsed range-selection guidance note for one calendar. | |
| 800 | + * Keeping one reusable node avoids repeated insertion while inactive guidance occupies no layout space. | |
| 709 | 801 | * |
| 710 | 802 | * @param {number|string} resource_id Booking resource ID. |
| 803 | + * @returns {jQuery} The prepared note, or an empty collection when guidance is unavailable. | |
| 711 | 804 | */ |
| 712 | - function wpbc_range_selection__hide_guidance( resource_id ){ | |
| 713 | - jQuery( '#wpbc_range_selection_guidance' + resource_id ).remove(); | |
| 714 | - } | |
| 805 | + function wpbc_range_selection__prepare_guidance( resource_id ){ | |
| 715 | 806 | |
| 716 | - | |
| 717 | - /** | |
| 718 | - * Show a persistent informational note after the first range click. | |
| 719 | - * The calendar parameter can be set to false by PHP or JavaScript to suppress this UI per resource. | |
| 720 | - * | |
| 721 | - * @param {number|string} resource_id Booking resource ID. | |
| 722 | - * @returns {boolean} True when the note was inserted. | |
| 723 | - */ | |
| 724 | - function wpbc_range_selection__show_guidance( resource_id ){ | |
| 725 | - | |
| 726 | 807 | var is_enabled = _wpbc.calendar__get_param_value( resource_id, 'range_selection_guidance_is_enabled' ); |
| 727 | 808 | var $booking_form = jQuery( '#booking_form_div' + resource_id ); |
| 728 | 809 | var $calendar_frame; |
| 729 | - var $note; | |
| 810 | + var $note = jQuery( '#wpbc_range_selection_guidance' + resource_id ); | |
| 730 | 811 | |
| 731 | - wpbc_range_selection__hide_guidance( resource_id ); | |
| 732 | - | |
| 733 | 812 | if ( |
| 734 | 813 | false === is_enabled |
| 735 | 814 | || 0 === is_enabled |
| 736 | 815 | || '0' === is_enabled |
| @@ -738,11 +817,17 @@ | ||
| 738 | 817 | || 'false' === String( is_enabled ).toLowerCase() |
| 739 | 818 | || 'dynamic' !== _wpbc.calendar__get_param_value( resource_id, 'days_select_mode' ) |
| 740 | 819 | || 0 === $booking_form.length |
| 741 | 820 | ) { |
| 742 | - return false; | |
| 821 | + $note.remove(); | |
| 822 | + return jQuery(); | |
| 743 | 823 | } |
| 744 | 824 | |
| 825 | + if ( 0 < $note.length ) { | |
| 826 | + $note.stop( true, true ).hide().attr( 'aria-hidden', 'true' ); | |
| 827 | + return $note; | |
| 828 | + } | |
| 829 | + | |
| 745 | 830 | $calendar_frame = $booking_form.find( '.block_hints.datepick' ).first(); |
| 746 | 831 | if ( 0 === $calendar_frame.length ) { |
| 747 | 832 | $calendar_frame = $booking_form.find( '.wpbc_cal_powered_by' ).first(); |
| 748 | 833 | if ( 0 === $calendar_frame.length ) { |
| @@ -747,9 +832,9 @@ | ||
| 747 | 832 | $calendar_frame = $booking_form.find( '.wpbc_cal_powered_by' ).first(); |
| 748 | 833 | if ( 0 === $calendar_frame.length ) { |
| 749 | 834 | $calendar_frame = $booking_form.find( '.bk_calendar_frame' ).first(); |
| 750 | 835 | if ( 0 === $calendar_frame.length ) { |
| 751 | - return false; | |
| 836 | + return jQuery(); | |
| 752 | 837 | } |
| 753 | 838 | } |
| 754 | 839 | } |
| 755 | 840 | |
| @@ -756,9 +841,11 @@ | ||
| 756 | 841 | $note = jQuery( '<div>', { |
| 757 | 842 | 'id': 'wpbc_range_selection_guidance' + resource_id, |
| 758 | 843 | 'class': 'wpbc_range_selection_guidance wpbc_front_end__message wpbc_fe_message_info', |
| 759 | 844 | 'role': 'status', |
| 760 | - 'aria-live': 'polite' | |
| 845 | + 'aria-live': 'polite', | |
| 846 | + 'aria-hidden': 'true', | |
| 847 | + 'style': 'display: none;' | |
| 761 | 848 | } ); |
| 762 | 849 | $note.append( jQuery( '<i>', { |
| 763 | 850 | 'class': 'menu_icon icon-1x wpbc_icn_info_outline', |
| 764 | 851 | 'aria-hidden': 'true' |
| @@ -765,8 +852,65 @@ | ||
| 765 | 852 | } ) ); |
| 766 | 853 | $note.append( jQuery( '<span>' ).text( _wpbc.get_message( 'message_range_selection_click_last_date' ) ) ); |
| 767 | 854 | $calendar_frame.after( $note ); |
| 768 | 855 | |
| 856 | + return $note; | |
| 857 | + } | |
| 858 | + | |
| 859 | + | |
| 860 | + /** | |
| 861 | + * Get the range-guidance animation duration for the current motion preference. | |
| 862 | + * | |
| 863 | + * @returns {number} Animation duration in milliseconds, or zero when reduced motion is preferred. | |
| 864 | + */ | |
| 865 | + function wpbc_range_selection__get_guidance_animation_duration(){ | |
| 866 | + | |
| 867 | + if ( | |
| 868 | + 'function' === typeof window.matchMedia | |
| 869 | + && window.matchMedia( '(prefers-reduced-motion: reduce)' ).matches | |
| 870 | + ) { | |
| 871 | + return 0; | |
| 872 | + } | |
| 873 | + | |
| 874 | + return 160; | |
| 875 | + } | |
| 876 | + | |
| 877 | + | |
| 878 | + /** | |
| 879 | + * Collapse the range-selection guidance so it does not reserve empty layout space. | |
| 880 | + * | |
| 881 | + * @param {number|string} resource_id Booking resource ID. | |
| 882 | + */ | |
| 883 | + function wpbc_range_selection__hide_guidance( resource_id ){ | |
| 884 | + | |
| 885 | + jQuery( '#wpbc_range_selection_guidance' + resource_id ) | |
| 886 | + .attr( 'aria-hidden', 'true' ) | |
| 887 | + .stop( true, true ) | |
| 888 | + .slideUp( wpbc_range_selection__get_guidance_animation_duration() ); | |
| 889 | + } | |
| 890 | + | |
| 891 | + | |
| 892 | + /** | |
| 893 | + * Show the prepared informational note after the first range click. | |
| 894 | + * The calendar parameter can be set to false by PHP or JavaScript to suppress this UI per resource. | |
| 895 | + * | |
| 896 | + * @param {number|string} resource_id Booking resource ID. | |
| 897 | + * @returns {boolean} True when the note was shown. | |
| 898 | + */ | |
| 899 | + function wpbc_range_selection__show_guidance( resource_id ){ | |
| 900 | + | |
| 901 | + var $note = wpbc_range_selection__prepare_guidance( resource_id ); | |
| 902 | + | |
| 903 | + if ( 0 === $note.length ) { | |
| 904 | + return false; | |
| 905 | + } | |
| 906 | + | |
| 907 | + $note | |
| 908 | + .stop( true, true ) | |
| 909 | + .slideDown( wpbc_range_selection__get_guidance_animation_duration() ) | |
| 910 | + .removeAttr( 'aria-hidden' ); | |
| 911 | + $note.find( 'span' ).text( _wpbc.get_message( 'message_range_selection_click_last_date' ) ); | |
| 912 | + | |
| 769 | 913 | return true; |
| 770 | 914 | } |
| 771 | 915 | |
| 772 | 916 | |
| @@ -1517,47 +1661,70 @@ | ||
| 1517 | 1661 | } |
| 1518 | 1662 | return false; |
| 1519 | 1663 | } |
| 1520 | 1664 | |
| 1521 | - /** | |
| 1522 | - * Is this date selectable in calendar (mainly it's means AVAILABLE date) | |
| 1523 | - * | |
| 1524 | - * @param {int|string} resource_id 1 | |
| 1525 | - * @param {string} sql_class_day '2023-08-11' | |
| 1526 | - * @returns {boolean} true | false | |
| 1527 | - */ | |
| 1528 | - 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 | + } | |
| 1529 | 1726 | |
| 1530 | - // Get Data -------------------------------------------------------------------------------------------------------- | |
| 1531 | - var date_bookings_obj = _wpbc.bookings_in_calendar__get_for_date( resource_id, sql_class_day ); | |
| 1532 | - if ( ! date_bookings_obj || 'undefined' === typeof ( date_bookings_obj[ 'day_availability' ] ) ) { | |
| 1533 | - return false; | |
| 1534 | - } | |
| 1535 | - | |
| 1536 | - var is_day_selectable = ( parseInt( date_bookings_obj[ 'day_availability' ] ) > 0 ); | |
| 1537 | - | |
| 1538 | - if ( typeof (date_bookings_obj[ 'summary' ]) === 'undefined' ){ | |
| 1539 | - return is_day_selectable; | |
| 1540 | - } | |
| 1541 | - | |
| 1542 | - if ( 'available' != date_bookings_obj[ 'summary']['status_for_day' ] ){ | |
| 1543 | - | |
| 1544 | - 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. | |
| 1545 | - var booking_statuses_arr = wpbc_get_booking_statuses__as_arr( date_bookings_obj ); | |
| 1546 | - | |
| 1547 | - if ( | |
| 1548 | - ( wpbc_booking_statuses__has( booking_statuses_arr, 'pending' ) ) | |
| 1549 | - || ( wpbc_booking_statuses__has( booking_statuses_arr, 'pending_pending' ) ) | |
| 1550 | - || ( wpbc_booking_statuses__has( booking_statuses_arr, 'pending_approved' ) ) | |
| 1551 | - || ( wpbc_booking_statuses__has( booking_statuses_arr, 'approved_pending' ) ) | |
| 1552 | - ){ | |
| 1553 | - is_day_selectable = (is_day_selectable) ? true : is_set_pending_days_selectable; | |
| 1554 | - } | |
| 1555 | - } | |
| 1556 | - | |
| 1557 | - return is_day_selectable; | |
| 1558 | - } | |
| 1559 | - | |
| 1560 | 1727 | /** |
| 1561 | 1728 | * Is date to check IN array of selected dates |
| 1562 | 1729 | * |
| 1563 | 1730 | * @param {date}js_date_to_check - JS Date - simple JavaScript Date object |
| @@ -2215,9 +2382,9 @@ | ||
| 2215 | 2382 | // Scroll to specific month, if we set dates in some future months |
| 2216 | 2383 | wpbc_calendar__scroll_to( resource_id, inst.dates[ 0 ].getFullYear(), inst.dates[ 0 ].getMonth()+1 ); |
| 2217 | 2384 | } |
| 2218 | 2385 | |
| 2219 | - return inst.dates.length; | |
| 2386 | + return wpbc_get__selected_dates_sql__as_arr( resource_id ).length; | |
| 2220 | 2387 | } |
| 2221 | 2388 | |
| 2222 | 2389 | return 0; |
| 2223 | 2390 | } |
| @@ -2340,9 +2507,12 @@ | ||
| 2340 | 2507 | } ); |
| 2341 | 2508 | } |
| 2342 | 2509 | } |
| 2343 | 2510 | |
| 2344 | - if ( url_params.has( 'wpbc_auto_fill' ) ){ | |
| 2511 | + if ( | |
| 2512 | + url_params.has( 'wpbc_auto_fill' ) | |
| 2513 | + && ! jQuery( 'body' ).hasClass( 'wp-admin' ) | |
| 2514 | + ){ | |
| 2345 | 2515 | |
| 2346 | 2516 | var wpbc_auto_fill_value = url_params.get( 'wpbc_auto_fill' ); |
| 2347 | 2517 | |
| 2348 | 2518 | // Convert back. Some systems do not like symbol '~' in URL, so we need to replace to some other symbols |
| @@ -2355,9 +2525,13 @@ | ||
| 2355 | 2525 | |
| 2356 | 2526 | /** |
| 2357 | 2527 | * Autofill / select booking form fields by values from the GET request parameter: ?wpbc_auto_fill= |
| 2358 | 2528 | * |
| 2359 | - * @param auto_fill_str | |
| 2529 | + * URL-provided field names are resolved through the exact-name DOM API so | |
| 2530 | + * they can never be interpreted as CSS selector syntax. | |
| 2531 | + * | |
| 2532 | + * @param {string} auto_fill_str Serialized field-name and value pairs. | |
| 2533 | + * @return {void} | |
| 2360 | 2534 | */ |
| 2361 | 2535 | function wpbc_auto_fill_booking_fields( auto_fill_str ){ // FixIn: 10.0.0.48. |
| 2362 | 2536 | |
| 2363 | 2537 | if ( '' == auto_fill_str ){ |
| @@ -2365,14 +2539,22 @@ | ||
| 2365 | 2539 | } |
| 2366 | 2540 | |
| 2367 | 2541 | // console.log( 'WPBC_AUTO_FILL_BOOKING_FIELDS( AUTO_FILL_STR )', auto_fill_str); |
| 2368 | 2542 | |
| 2369 | - var fields_arr = wpbc_auto_fill_booking_fields__parse( auto_fill_str ); | |
| 2370 | - | |
| 2371 | - for ( let i = 0; i < fields_arr.length; i++ ){ | |
| 2372 | - jQuery( '[name="' + fields_arr[ i ][ 'name' ] + '"]' ).val( fields_arr[ i ][ 'value' ] ); | |
| 2373 | - } | |
| 2374 | -} | |
| 2543 | + var fields_arr = wpbc_auto_fill_booking_fields__parse( auto_fill_str ); | |
| 2544 | + | |
| 2545 | + for ( let i = 0; i < fields_arr.length; i++ ){ | |
| 2546 | + var field_name = String( fields_arr[ i ][ 'name' ] || '' ); | |
| 2547 | + if ( '' === field_name ) { | |
| 2548 | + continue; | |
| 2549 | + } | |
| 2550 | + | |
| 2551 | + var field_elements = document.getElementsByName( field_name ); | |
| 2552 | + if ( 0 < field_elements.length ) { | |
| 2553 | + jQuery( field_elements ).val( fields_arr[ i ][ 'value' ] ); | |
| 2554 | + } | |
| 2555 | + } | |
| 2556 | +} | |
| 2375 | 2557 | |
| 2376 | 2558 | /** |
| 2377 | 2559 | * Parse data from get parameter: ?wpbc_auto_fill=visitors231^2~max_capacity231^2 |
| 2378 | 2560 | * |