| @@ -1,10 +1,79 @@ | ||
| 1 | -var time_buffer_value = 0; // Customization of bufer time for DAN | |
| 2 | -var is_check_start_time_gone = false; // Check start time or end time for the time, which is gone already TODAY. | |
| 3 | 1 | var start_time_checking_index; |
| 4 | -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 5 | 2 | |
| 6 | 3 | /** |
| 4 | + * Check if the date has only Working Time limits, without real bookings or manually blocked time slots. | |
| 5 | + * | |
| 6 | + * Working Time intervals still have to stay in the booking data for validation and tooltips, | |
| 7 | + * but they should not produce the small dots inside calendar day cells. | |
| 8 | + * | |
| 9 | + * @param {Object} date_bookings_obj | |
| 10 | + * @param {Array} child_resources_arr | |
| 11 | + * @returns {boolean} | |
| 12 | + */ | |
| 13 | +function wpbc_is_date_has_only_working_time_limits_for_dots( date_bookings_obj, child_resources_arr ) { | |
| 14 | + | |
| 15 | + var has_working_time_limits = false; | |
| 16 | + var has_real_time_limits = false; | |
| 17 | + var resource_day_obj; | |
| 18 | + var time_details_obj; | |
| 19 | + var time_details; | |
| 20 | + var source_type; | |
| 21 | + | |
| 22 | + if ( ( ! date_bookings_obj ) || ( null === child_resources_arr ) ) { | |
| 23 | + return false; | |
| 24 | + } | |
| 25 | + | |
| 26 | + if ( | |
| 27 | + ( date_bookings_obj[ 'summary' ] ) | |
| 28 | + && ( date_bookings_obj[ 'summary' ][ 'status_for_bookings' ] ) | |
| 29 | + && ( '' !== date_bookings_obj[ 'summary' ][ 'status_for_bookings' ] ) | |
| 30 | + ) { | |
| 31 | + return false; | |
| 32 | + } | |
| 33 | + | |
| 34 | + for ( var i = 0; i < child_resources_arr.length; i++ ) { | |
| 35 | + | |
| 36 | + resource_day_obj = date_bookings_obj[ child_resources_arr[ i ] ]; | |
| 37 | + | |
| 38 | + if ( ! resource_day_obj ) { | |
| 39 | + continue; | |
| 40 | + } | |
| 41 | + | |
| 42 | + time_details_obj = resource_day_obj[ '__booked__times__details' ]; | |
| 43 | + | |
| 44 | + if ( ! time_details_obj ) { | |
| 45 | + if ( | |
| 46 | + ( resource_day_obj.booked_time_slots ) | |
| 47 | + && ( resource_day_obj.booked_time_slots.merged_seconds ) | |
| 48 | + && ( resource_day_obj.booked_time_slots.merged_seconds.length > 0 ) | |
| 49 | + ) { | |
| 50 | + has_real_time_limits = true; | |
| 51 | + } | |
| 52 | + continue; | |
| 53 | + } | |
| 54 | + | |
| 55 | + for ( var time_key in time_details_obj ) { | |
| 56 | + | |
| 57 | + if ( ! time_details_obj.hasOwnProperty( time_key ) ) { | |
| 58 | + continue; | |
| 59 | + } | |
| 60 | + | |
| 61 | + time_details = time_details_obj[ time_key ]; | |
| 62 | + source_type = ( time_details && ( 'undefined' !== typeof( time_details[ 'source_type' ] ) ) ) ? time_details[ 'source_type' ] : 'booking'; | |
| 63 | + | |
| 64 | + if ( 'working_time' === source_type ) { | |
| 65 | + has_working_time_limits = true; | |
| 66 | + } else { | |
| 67 | + has_real_time_limits = true; | |
| 68 | + } | |
| 69 | + } | |
| 70 | + } | |
| 71 | + | |
| 72 | + return ( has_working_time_limits && ! has_real_time_limits ); | |
| 73 | +} | |
| 74 | + | |
| 75 | +/** | |
| 7 | 76 | * Get dots for partially booked dates. |
| 8 | 77 | * For parent booking resources with specific capacity, |
| 9 | 78 | * System do not show partially booked dates, if at least one child booking resource fully available |
| 10 | 79 | * Otherwise it show maximum number of time-slot in one specific child booking resource |
| @@ -12,20 +81,29 @@ | ||
| 12 | 81 | * @param param_calendar_id ID of booking resource |
| 13 | 82 | * @param my_thisDateTime timestamp of date |
| 14 | 83 | * @returns {string} |
| 15 | 84 | */ |
| 16 | -function wpbc_show_date_info_top( param_calendar_id, my_thisDateTime ){ | |
| 85 | +function wpbc_show_date_info_top( param_calendar_id, my_thisDateTime ) { | |
| 17 | 86 | |
| 18 | - var resource_id = parseInt( param_calendar_id.replace( "calendar_booking", '' ) ); | |
| 87 | + var resource_id = parseInt(param_calendar_id.replace("calendar_booking", '')); | |
| 19 | 88 | |
| 89 | + if (isNaN(resource_id)) { | |
| 90 | + return ''; // FixIn: 10.9.5.2. | |
| 91 | + } | |
| 92 | + | |
| 20 | 93 | // console.log( _wpbc.bookings_in_calendar__get( resource_id ) ); // for debug |
| 21 | 94 | |
| 22 | 95 | // 1. Get child booking resources or single booking resource that exist in dates : [1] | [1,14,15,17] |
| 23 | - var child_resources_arr = wpbc_clone_obj( _wpbc.booking__get_param_value( resource_id, 'resources_id_arr__in_dates' ) ); | |
| 96 | + var child_resources_arr = wpbc_clone_obj(_wpbc.booking__get_param_value(resource_id, 'resources_id_arr__in_dates')); | |
| 24 | 97 | |
| 25 | 98 | // '2023-08-21' |
| 26 | - var sql_date = wpbc__get__sql_class_date( new Date( my_thisDateTime ) ); | |
| 99 | + var sql_date = wpbc__get__sql_class_date(new Date(my_thisDateTime)); | |
| 100 | + var date_bookings_obj = _wpbc.bookings_in_calendar__get_for_date(resource_id, sql_date); | |
| 27 | 101 | |
| 102 | + if ( wpbc_is_date_has_only_working_time_limits_for_dots( date_bookings_obj, child_resources_arr ) ) { | |
| 103 | + return ''; | |
| 104 | + } | |
| 105 | + | |
| 28 | 106 | var child_resource_id; |
| 29 | 107 | var merged_seconds; |
| 30 | 108 | var dots_count = 0; |
| 31 | 109 | |
| @@ -30,36 +108,35 @@ | ||
| 30 | 108 | var dots_count = 0; |
| 31 | 109 | |
| 32 | 110 | var dots_in__resources = []; |
| 33 | 111 | |
| 34 | - // Loop all resources ID | |
| 35 | - for ( var res_key in child_resources_arr ){ | |
| 112 | + // Loop all resources ID. | |
| 113 | + if (child_resources_arr !== null) { | |
| 114 | + for (child_resource_id of child_resources_arr) { // FixIn: 10.9.5.1. | |
| 36 | 115 | |
| 37 | - child_resource_id = child_resources_arr[ res_key ]; | |
| 116 | + // _wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[12].booked_time_slots.merged_seconds = [ "07:00:11 - 07:30:02", "10:00:11 - 00:00:00" ] | |
| 117 | + // _wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[2].booked_time_slots.merged_seconds = [ [ 25211, 27002 ], [ 36011, 86400 ] ] | |
| 38 | 118 | |
| 39 | - // _wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[12].booked_time_slots.merged_seconds = [ "07:00:11 - 07:30:02", "10:00:11 - 00:00:00" ] | |
| 40 | - // _wpbc.bookings_in_calendar__get_for_date(2,'2023-08-21')[2].booked_time_slots.merged_seconds = [ [ 25211, 27002 ], [ 36011, 86400 ] ] | |
| 119 | + if (false !== date_bookings_obj) { | |
| 120 | + merged_seconds = date_bookings_obj[child_resource_id].booked_time_slots.merged_seconds; // [ [ 25211, 27002 ], [ 36011, 86400 ] ] | |
| 121 | + } else { | |
| 122 | + merged_seconds = []; | |
| 123 | + } | |
| 41 | 124 | |
| 42 | - if ( false !== _wpbc.bookings_in_calendar__get_for_date( resource_id, sql_date ) ){ | |
| 43 | - merged_seconds = _wpbc.bookings_in_calendar__get_for_date( resource_id, sql_date )[ child_resource_id ].booked_time_slots.merged_seconds; // [ [ 25211, 27002 ], [ 36011, 86400 ] ] | |
| 44 | - } else { | |
| 45 | - merged_seconds = []; | |
| 46 | - } | |
| 125 | + if (0 === merged_seconds.length) { | |
| 126 | + return ''; // Day available | |
| 127 | + } | |
| 47 | 128 | |
| 48 | - if ( 0 === merged_seconds.length ){ | |
| 49 | - return ''; // Day available | |
| 50 | - } | |
| 129 | + for (var i = 0; i < merged_seconds.length; i++) { | |
| 130 | + if (!wpbc_is_this_timeslot__full_day_booked(merged_seconds[i])) { // Check if this fully booked date. If yes, then do not count it | |
| 131 | + dots_count++; | |
| 132 | + } | |
| 133 | + } | |
| 51 | 134 | |
| 52 | - for ( var i = 0; i < merged_seconds.length; i++ ){ | |
| 53 | - if ( ! wpbc_is_this_timeslot__full_day_booked( merged_seconds[i] ) ){ // Check if this fully booked date. If yes, then do not count it | |
| 54 | - dots_count++; | |
| 55 | - } | |
| 135 | + dots_in__resources.push(dots_count); | |
| 136 | + dots_count = 0; | |
| 56 | 137 | } |
| 57 | - | |
| 58 | - dots_in__resources.push( dots_count ); | |
| 59 | - dots_count = 0; | |
| 60 | 138 | } |
| 61 | - | |
| 62 | 139 | var dots_count_max = Math.max.apply( Math, dots_in__resources ); // Get maximum value in array [ 1, 5, 3] -> 5 |
| 63 | 140 | |
| 64 | 141 | var dot_content = ''; |
| 65 | 142 | for ( var d = 0; d < dots_count_max; d++ ){ |
| @@ -70,27 +147,92 @@ | ||
| 70 | 147 | |
| 71 | 148 | return dot_content; |
| 72 | 149 | } |
| 73 | 150 | |
| 151 | +/** | |
| 152 | + * Show Date Info at bottom of the Day Cell | |
| 153 | + * | |
| 154 | + * @param param_calendar_id 'calendar_booking1' | |
| 155 | + * @param my_thisDateTime 56567557757 | |
| 156 | + * @returns {string} | |
| 157 | + */ | |
| 158 | +function wpbc_show_date_info_bottom( param_calendar_id, my_thisDateTime ) { | |
| 74 | 159 | |
| 75 | -function wpbc_show_date_info_bottom( param_calendar_id, my_thisDateTime ) { | |
| 160 | + var bottom_hint_arr = []; | |
| 76 | 161 | |
| 77 | - if ( typeof( wpbc_show_day_cost_in_date_bottom ) == 'function' ) { | |
| 162 | + // Cost Hint | |
| 163 | + if ( typeof (wpbc_show_day_cost_in_date_bottom) == 'function' ) { | |
| 164 | + var cost_hint = wpbc_show_day_cost_in_date_bottom( param_calendar_id, my_thisDateTime ); | |
| 165 | + if ( '' !== cost_hint ) { | |
| 166 | + bottom_hint_arr.push( wpbc_show_day_cost_in_date_bottom( param_calendar_id, my_thisDateTime ) ); | |
| 167 | + } | |
| 168 | + } | |
| 78 | 169 | |
| 79 | - return wpbc_show_day_cost_in_date_bottom( param_calendar_id, my_thisDateTime ); | |
| 170 | + // Availability Hint // FixIn: 10.6.4.1. | |
| 171 | + var availability = wpbc_get_in_date_availability_hint( param_calendar_id, my_thisDateTime ) | |
| 172 | + if ( '' !== availability ) { | |
| 173 | + bottom_hint_arr.push( availability ); | |
| 174 | + } | |
| 80 | 175 | |
| 176 | + var bottom_hint = bottom_hint_arr.join( '' ); | |
| 177 | + return bottom_hint; | |
| 178 | +} | |
| 179 | + | |
| 180 | +/** | |
| 181 | + * Get Availability Hint for in Day Cell | |
| 182 | + * | |
| 183 | + * @param param_calendar_id | |
| 184 | + * @param my_thisDateTime | |
| 185 | + * @returns {string} | |
| 186 | + */ | |
| 187 | +function wpbc_get_in_date_availability_hint( param_calendar_id, my_thisDateTime ) { // FixIn: 10.6.4.1. | |
| 188 | + | |
| 189 | + /* | |
| 190 | + var sql_date = wpbc__get__sql_class_date( new Date( my_thisDateTime ) ); // '2023-08-21' | |
| 191 | + var resource_id = parseInt( param_calendar_id.replace( "calendar_booking", '' ) ); // 1 | |
| 192 | + var day_availability_obj = _wpbc.bookings_in_calendar__get_for_date( resource_id, sql_date ); // obj | |
| 193 | + | |
| 194 | + if ( 'undefined' !== typeof (day_availability_obj.day_availability) ) { | |
| 195 | + return '<strong>' + day_availability_obj.day_availability + '</strong> ' + 'available'; | |
| 81 | 196 | } else { |
| 82 | 197 | return ''; |
| 83 | 198 | } |
| 199 | + */ | |
| 200 | + | |
| 201 | + var resource_id = parseInt( param_calendar_id.replace( "calendar_booking", '' ) ); | |
| 202 | + | |
| 203 | + // console.log( _wpbc.bookings_in_calendar__get( resource_id ) ); // for debug | |
| 204 | + | |
| 205 | + // 1. Get child booking resources or single booking resource that exist in dates : [1] | [1,14,15,17] | |
| 206 | + // var child_resources_arr = wpbc_clone_obj( _wpbc.booking__get_param_value( resource_id, 'resources_id_arr__in_dates' ) ); | |
| 207 | + | |
| 208 | + // '2023-08-21' | |
| 209 | + var sql_date = wpbc__get__sql_class_date( new Date( my_thisDateTime ) ); | |
| 210 | + | |
| 211 | + var hint__in_day__availability = ''; | |
| 212 | + | |
| 213 | + var get_for_date_obj = _wpbc.bookings_in_calendar__get_for_date( resource_id, sql_date ); | |
| 214 | + | |
| 215 | + if ( false !== get_for_date_obj ){ | |
| 216 | + | |
| 217 | + if ( | |
| 218 | + (undefined != get_for_date_obj[ 'summary' ]) | |
| 219 | + && (undefined != get_for_date_obj[ 'summary' ].hint__in_day__availability) | |
| 220 | + ){ | |
| 221 | + hint__in_day__availability = get_for_date_obj[ 'summary' ].hint__in_day__availability; // "5 available" | |
| 222 | + } | |
| 223 | + | |
| 224 | + } | |
| 225 | + | |
| 226 | + return hint__in_day__availability; | |
| 84 | 227 | } |
| 85 | 228 | |
| 86 | 229 | |
| 87 | - | |
| 88 | 230 | /** |
| 89 | 231 | * Hide Tippy tooltip on scroll, to prevent issue on mobile touch devices of showing tooltip at top left corner! |
| 90 | 232 | * @param evt |
| 91 | 233 | */ |
| 92 | -jQuery( window ).on( 'scroll', function ( event ){ //FixIn: 9.2.1.5 //FixIn: 9.4.3.3 | |
| 234 | +jQuery( window ).on( 'scroll', function ( event ){ //FixIn: 9.2.1.5 // FixIn: 9.4.3.3. | |
| 93 | 235 | if ( 'function' === typeof( wpbc_tippy ) ){ |
| 94 | 236 | wpbc_tippy.hideAll(); |
| 95 | 237 | } |
| 96 | 238 | } ); |
| @@ -101,9 +243,9 @@ | ||
| 101 | 243 | * @param resource_id |
| 102 | 244 | * @param form_elements |
| 103 | 245 | * @returns {boolean} |
| 104 | 246 | */ |
| 105 | -function wpbc_is_time_field_in_booking_form( resource_id, form_elements ){ //FixIn: 8.2.1.28 | |
| 247 | +function wpbc_is_time_field_in_booking_form( resource_id, form_elements ){ // FixIn: 8.2.1.28. | |
| 106 | 248 | |
| 107 | 249 | var count = form_elements.length; |
| 108 | 250 | var start_time = false; |
| 109 | 251 | var end_time = false; |
| @@ -117,15 +259,15 @@ | ||
| 117 | 259 | |
| 118 | 260 | element = form_elements[ i ]; |
| 119 | 261 | |
| 120 | 262 | // Skip elements from garbage |
| 121 | - if ( jQuery( element ).closest( '.booking_form_garbage' ).length ){ //FixIn: 7.1.2.14 | |
| 263 | + if ( jQuery( element ).closest( '.booking_form_garbage' ).length ){ // FixIn: 7.1.2.14. | |
| 122 | 264 | continue; |
| 123 | 265 | } |
| 124 | 266 | |
| 125 | 267 | if ( |
| 126 | 268 | ( element.name != undefined ) |
| 127 | - && ( element.name.indexOf( 'hint' ) !== -1 ) //FixIn: 9.5.5.2 | |
| 269 | + && ( element.name.indexOf( 'hint' ) !== -1 ) // FixIn: 9.5.5.2. | |
| 128 | 270 | ){ |
| 129 | 271 | var my_element = element.name; //.toString(); |
| 130 | 272 | if ( my_element.indexOf( 'rangetime' ) !== -1 ){ // Range Time |
| 131 | 273 | |
| @@ -154,19 +296,154 @@ | ||
| 154 | 296 | |
| 155 | 297 | return false; |
| 156 | 298 | } |
| 157 | 299 | |
| 300 | +function wpbc_is_change_over_enabled_for_resource( resource_id ) { | |
| 158 | 301 | |
| 159 | -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 302 | + if ( ( 'undefined' !== typeof resource_id ) && ( null !== resource_id ) ) { | |
| 303 | + var resource_change_over = _wpbc.calendar__get_param_value( resource_id, 'is_enabled_change_over' ); | |
| 304 | + if ( '' !== resource_change_over ) { | |
| 305 | + return ( true === resource_change_over ) || ( 'true' === resource_change_over ); | |
| 306 | + } | |
| 307 | + } | |
| 308 | + | |
| 309 | + return true === _wpbc.get_other_param( 'is_enabled_change_over' ); | |
| 310 | +} | |
| 311 | + | |
| 312 | + | |
| 313 | +/** | |
| 314 | + * Check if the selected date/time is already in the past compared to "today_arr". | |
| 315 | + * | |
| 316 | + * Behavior notes: | |
| 317 | + * - If "is_enabled_change_over" is enabled, always returns false (no restriction). | |
| 318 | + * - `sort_date_array[0]` is expected to be the earliest selected date (sorted ascending). | |
| 319 | + * - `today_arr` is expected to be: [YYYY, MM, DD, HH, mm] (strings or numbers). | |
| 320 | + * - `myTime` is expected to be "HH:MM" (24h). | |
| 321 | + * | |
| 322 | + * @param {string} myTime Time string in "HH:MM" format. | |
| 323 | + * @param {Array<Array<string|number>>} sort_date_array Array of date arrays; first element is used as date to check. | |
| 324 | + * @returns {boolean} True if selected date/time is in the past, otherwise false. | |
| 325 | + */ | |
| 326 | +function wpbc_is_time_in_the_past_for_today(myTime, sort_date_array, resource_id) { | |
| 327 | + | |
| 328 | + var allow_past_context = _wpbc.get_other_param( 'this_page_allow_past' ); | |
| 329 | + var edit_booking_hash_context = _wpbc.get_other_param( 'this_page_booking_hash' ); | |
| 330 | + if ( | |
| 331 | + ( '1' === String( allow_past_context ) ) | |
| 332 | + || ( 1 === allow_past_context ) | |
| 333 | + || ( true === allow_past_context ) | |
| 334 | + || ( '' !== String( edit_booking_hash_context || '' ) ) | |
| 335 | + || ( location.href.indexOf( 'booking_hash' ) > -1 ) | |
| 336 | + || ( location.href.indexOf( 'allow_past' ) > -1 ) | |
| 337 | + ) { | |
| 338 | + return false; | |
| 339 | + } | |
| 340 | + | |
| 341 | + // FixIn: 10.14.10.2. | |
| 342 | + if ( true === wpbc_is_change_over_enabled_for_resource( resource_id ) ) { | |
| 343 | + return false; | |
| 344 | + } | |
| 345 | + var date_to_check = sort_date_array[0]; | |
| 346 | + if ( parseInt( date_to_check[0] ) < parseInt( _wpbc.get_other_param( 'today_arr' )[0] ) ) { | |
| 347 | + return true; | |
| 348 | + } | |
| 349 | + if ( | |
| 350 | + (parseInt( date_to_check[0] ) == parseInt( _wpbc.get_other_param( 'today_arr' )[0] )) && | |
| 351 | + (parseInt( date_to_check[1] ) < parseInt( _wpbc.get_other_param( 'today_arr' )[1] )) | |
| 352 | + ) { | |
| 353 | + return true; | |
| 354 | + } | |
| 355 | + if ( | |
| 356 | + (parseInt( date_to_check[0] ) == parseInt( _wpbc.get_other_param( 'today_arr' )[0] )) && | |
| 357 | + (parseInt( date_to_check[1] ) == parseInt( _wpbc.get_other_param( 'today_arr' )[1] )) && | |
| 358 | + (parseInt( date_to_check[2] ) < parseInt( _wpbc.get_other_param( 'today_arr' )[2] )) | |
| 359 | + ) { | |
| 360 | + return true; | |
| 361 | + } | |
| 362 | + if ( | |
| 363 | + (parseInt( date_to_check[0] ) == parseInt( _wpbc.get_other_param( 'today_arr' )[0] )) && | |
| 364 | + (parseInt( date_to_check[1] ) == parseInt( _wpbc.get_other_param( 'today_arr' )[1] )) && | |
| 365 | + (parseInt( date_to_check[2] ) == parseInt( _wpbc.get_other_param( 'today_arr' )[2] )) | |
| 366 | + ) { | |
| 367 | + var mytime_value = myTime.split( ":" ); | |
| 368 | + mytime_value = parseInt( mytime_value[0] ) * 60 + parseInt( mytime_value[1] ); | |
| 369 | + | |
| 370 | + var current_time_value = parseInt( _wpbc.get_other_param( 'today_arr' )[3] ) * 60 + parseInt( _wpbc.get_other_param( 'today_arr' )[4] ); | |
| 371 | + | |
| 372 | + if ( current_time_value > mytime_value ) { | |
| 373 | + return true; | |
| 374 | + } | |
| 375 | + } | |
| 376 | + return false; | |
| 377 | +} | |
| 378 | + | |
| 379 | +/** | |
| 380 | + * Validate a time string. | |
| 381 | + * | |
| 382 | + * Supported formats: | |
| 383 | + * - 24-hour time: "H:MM" or "HH:MM" | |
| 384 | + * Examples: "0:00", "09:30", "23:59", "24:00" | |
| 385 | + * Notes: "24:00" is allowed, but "24:01" is not. | |
| 386 | + * | |
| 387 | + * - 12-hour time: "H:MM AM/PM" (AM/PM is case-insensitive; spaces are optional) | |
| 388 | + * Examples: "9:30 AM", "09:30pm", "12:05 PM" | |
| 389 | + * | |
| 390 | + * @param {string} time_str Raw time string entered by the user. | |
| 391 | + * @returns {boolean} True if the string matches a valid supported time format. | |
| 392 | + */ | |
| 393 | +function wpbc_is_valid_time_string(time_str) { | |
| 394 | + | |
| 395 | + if ( typeof time_str !== 'string' ) { | |
| 396 | + return false; | |
| 397 | + } | |
| 398 | + | |
| 399 | + const str = time_str.trim(); | |
| 400 | + if ( str === '' ) { | |
| 401 | + return false; | |
| 402 | + } | |
| 403 | + | |
| 404 | + // 1-2 digit hours, 2 digit minutes, optional AM/PM (case-insensitive). | |
| 405 | + const match = str.match( /^(\d{1,2}):(\d{2})(?:\s*([AaPp][Mm]))?$/ ); | |
| 406 | + if ( ! match ) { | |
| 407 | + return false; | |
| 408 | + } | |
| 409 | + | |
| 410 | + const hour = Number( match[1] ); | |
| 411 | + const minute = Number( match[2] ); | |
| 412 | + const ampm = match[3] ? match[3].toUpperCase() : null; | |
| 413 | + | |
| 414 | + if ( ! Number.isInteger( hour ) || ! Number.isInteger( minute ) ) { | |
| 415 | + return false; | |
| 416 | + } | |
| 417 | + | |
| 418 | + if ( minute < 0 || minute > 59 ) { | |
| 419 | + return false; | |
| 420 | + } | |
| 421 | + | |
| 422 | + // 12-hour mode (AM/PM provided): hour must be 1..12. | |
| 423 | + if ( ampm ) { | |
| 424 | + return hour >= 1 && hour <= 12; | |
| 425 | + } | |
| 426 | + | |
| 427 | + // 24-hour mode (no AM/PM): hour must be 0..24, but 24 only allowed with :00. | |
| 428 | + if ( hour < 0 || hour > 24 ) { | |
| 429 | + return false; | |
| 430 | + } | |
| 431 | + if ( hour === 24 && minute !== 0 ) { | |
| 432 | + return false; | |
| 433 | + } | |
| 434 | + | |
| 435 | + return true; | |
| 436 | +} | |
| 437 | + | |
| 438 | + | |
| 160 | 439 | //TODO: Continue Refactoring here 2018-04-21 |
| 161 | -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 162 | 440 | |
| 163 | - | |
| 164 | - //PS: This function from ../booking/inc/js/personal.js | |
| 441 | + //PS: This function from personal.js | |
| 165 | 442 | function wpbc_is_this_time_selection_not_available( resource_id, form_elements ){ |
| 166 | 443 | |
| 167 | 444 | // Skip this checking if we are in the Admin panel at Add booking page |
| 168 | - if ( location.href.indexOf( 'page=wpbc-new' ) > 0 ) { | |
| 445 | + if ( ( location.href.indexOf( 'page=wpbc' ) > 0 ) && ( location.href.indexOf( 'tab=add-booking' ) > 0 ) ) { | |
| 169 | 446 | return false; |
| 170 | 447 | } |
| 171 | 448 | |
| 172 | 449 | var count = form_elements.length; |
| @@ -186,20 +463,24 @@ | ||
| 186 | 463 | |
| 187 | 464 | element = form_elements[ i ]; |
| 188 | 465 | |
| 189 | 466 | // Skip elements from garbage |
| 190 | - if ( jQuery( element ).closest( '.booking_form_garbage' ).length ){ //FixIn: 7.1.2.14 | |
| 467 | + if ( jQuery( element ).closest( '.booking_form_garbage' ).length ){ // FixIn: 7.1.2.14. | |
| 191 | 468 | continue; |
| 192 | 469 | } |
| 193 | 470 | |
| 471 | + if ( '1' === String( jQuery( element ).attr( 'data-wpbc-booking-submit-ignore' ) || '' ) ) { | |
| 472 | + continue; | |
| 473 | + } | |
| 474 | + | |
| 194 | 475 | if ( |
| 195 | 476 | ( element.name != undefined ) |
| 196 | - && ( element.name.indexOf( 'hint' ) === -1 ) //FixIn: 9.5.5.2 //FixIn: 9.6.3.9 | |
| 477 | + && ( element.name.indexOf( 'hint' ) === -1 ) //FixIn: 9.5.5.2 // FixIn: 9.6.3.9. | |
| 197 | 478 | ){ |
| 198 | 479 | var my_element = element.name; //.toString(); |
| 199 | 480 | if ( my_element.indexOf( 'rangetime' ) !== -1 ){ // Range Time |
| 200 | 481 | if ( element.value == '' ){ //FixIn: 7.0.Beta.19 |
| 201 | - var notice_message_id = wpbc_front_end__show_message__warning( element, _wpbc.get_message( 'message_check_required' ) ); | |
| 482 | + var notice_message_id = wpbc_front_end__show_message__warning( element, _wpbc.get_message( 'message_check_required' ), 'text' ); | |
| 202 | 483 | return true; |
| 203 | 484 | } |
| 204 | 485 | var my_rangetime = element.value.split( '-' ); |
| 205 | 486 | if ( my_rangetime.length > 1 ){ |
| @@ -253,10 +534,10 @@ | ||
| 253 | 534 | |
| 254 | 535 | var valid_time = true; |
| 255 | 536 | if ( (start_time == '') || (end_time == '') ) valid_time = false; |
| 256 | 537 | |
| 257 | - if ( !isValidTimeTextField( start_time ) ) valid_time = false; | |
| 258 | - if ( !isValidTimeTextField( end_time ) ) valid_time = false; | |
| 538 | + if ( !wpbc_is_valid_time_string( start_time ) ) valid_time = false; | |
| 539 | + if ( !wpbc_is_valid_time_string( end_time ) ) valid_time = false; | |
| 259 | 540 | |
| 260 | 541 | if ( valid_time === true ) |
| 261 | 542 | if ( |
| 262 | 543 | (typeof(checkRecurentTimeInside) == 'function') && |
| @@ -277,16 +558,16 @@ | ||
| 277 | 558 | } |
| 278 | 559 | } |
| 279 | 560 | |
| 280 | 561 | if ( valid_time !== true ){ |
| 281 | - //return false; // do not show warning for setting pending days selectable, if making booking for time-slot //FixIn: 7.0.1.23 | |
| 282 | - if ( (_wpbc.get_other_param( 'is_enabled_change_over' )) && (element_start !== false) && (element_end !== false) ){ //FixIn:6.1.1.1 | |
| 283 | - wpbc_front_end__show_message__warning_under_element( '#date_booking' + resource_id, _wpbc.get_message( 'message_check_no_selected_dates' ) ); | |
| 562 | + //return false; // do not show warning for setting pending days selectable, if making booking for time-slot // FixIn: 7.0.1.23. | |
| 563 | + if ( ( wpbc_is_change_over_enabled_for_resource( resource_id ) ) && (element_start !== false) && (element_end !== false) ){ // FixIn: 6.1.1.1. | |
| 564 | + wpbc_front_end__show_message__warning( '#booking_form_div' + resource_id + ' .bk_calendar_frame', _wpbc.get_message( 'message_check_no_selected_dates' ), 'text' ); | |
| 284 | 565 | } |
| 285 | - if ( element_rangetime !== false ){ wpbc_front_end__show_message__warning_under_element( element_rangetime, _wpbc.get_message( 'message_error_range_time' ) ); } | |
| 286 | - if ( element_duration !== false ){ wpbc_front_end__show_message__warning_under_element( element_duration, _wpbc.get_message( 'message_error_duration_time' ) ); } | |
| 287 | - if ( element_start !== false ){ wpbc_front_end__show_message__warning_under_element( element_start, _wpbc.get_message( 'message_error_start_time' ) ); } | |
| 288 | - if ( element_end !== false ){ wpbc_front_end__show_message__warning_under_element( element_end, _wpbc.get_message( 'message_error_end_time' ) ); } | |
| 566 | + if ( element_rangetime !== false ){ wpbc_front_end__show_message__warning_under_element( element_rangetime, _wpbc.get_message( 'message_error_range_time' ), 'text' ); } | |
| 567 | + if ( element_duration !== false ){ wpbc_front_end__show_message__warning_under_element( element_duration, _wpbc.get_message( 'message_error_duration_time' ), 'text' ); } | |
| 568 | + if ( element_start !== false ){ wpbc_front_end__show_message__warning_under_element( element_start, _wpbc.get_message( 'message_error_start_time' ), 'text' ); } | |
| 569 | + if ( element_end !== false ){ wpbc_front_end__show_message__warning_under_element( element_end, _wpbc.get_message( 'message_error_end_time' ), 'text' ); } | |
| 289 | 570 | |
| 290 | 571 | return true; |
| 291 | 572 | |
| 292 | 573 | } else { |
| @@ -297,44 +578,20 @@ | ||
| 297 | 578 | |
| 298 | 579 | |
| 299 | 580 | } |
| 300 | 581 | |
| 582 | + function checkTimeInside( mytime, is_start_time, bk_type ){ | |
| 301 | 583 | |
| 302 | - function isTimeTodayGone( myTime, sort_date_array ){ | |
| 303 | - var date_to_check = sort_date_array[ 0 ]; | |
| 304 | - if ( is_check_start_time_gone == false ){ | |
| 305 | - date_to_check = sort_date_array[ (sort_date_array.length - 1) ]; | |
| 306 | - } | |
| 584 | + var my_dates_str = document.getElementById( 'date_booking' + bk_type ).value; // GET DATES From TEXTAREA | |
| 307 | 585 | |
| 308 | - if ( parseInt( date_to_check[ 0 ] ) < parseInt( _wpbc.get_other_param( 'today_arr' )[ 0 ] ) ) return true; | |
| 309 | - if ( (parseInt( date_to_check[ 0 ] ) == parseInt( _wpbc.get_other_param( 'today_arr' )[ 0 ] )) && (parseInt( date_to_check[ 1 ] ) < parseInt( _wpbc.get_other_param( 'today_arr' )[ 1 ] )) ) | |
| 310 | - return true; | |
| 311 | - if ( (parseInt( date_to_check[ 0 ] ) == parseInt( _wpbc.get_other_param( 'today_arr' )[ 0 ] )) && (parseInt( date_to_check[ 1 ] ) == parseInt( _wpbc.get_other_param( 'today_arr' )[ 1 ] )) && (parseInt( date_to_check[ 2 ] ) < parseInt( _wpbc.get_other_param( 'today_arr' )[ 2 ] )) ) | |
| 312 | - return true; | |
| 313 | - if ( (parseInt( date_to_check[ 0 ] ) == parseInt( _wpbc.get_other_param( 'today_arr' )[ 0 ] )) && | |
| 314 | - (parseInt( date_to_check[ 1 ] ) == parseInt( _wpbc.get_other_param( 'today_arr' )[ 1 ] )) && | |
| 315 | - (parseInt( date_to_check[ 2 ] ) == parseInt( _wpbc.get_other_param( 'today_arr' )[ 2 ] )) ){ | |
| 316 | - var mytime_value = myTime.split( ":" ); | |
| 317 | - mytime_value = mytime_value[ 0 ] * 60 + parseInt( mytime_value[ 1 ] ); | |
| 586 | + if ( my_dates_str.indexOf( ' - ' ) != 0 ){ | |
| 318 | 587 | |
| 319 | - var current_time_value = _wpbc.get_other_param( 'today_arr' )[ 3 ] * 60 + parseInt( _wpbc.get_other_param( 'today_arr' )[ 4 ] ); | |
| 320 | - | |
| 321 | - if ( current_time_value > mytime_value ) return true; | |
| 322 | - | |
| 588 | + my_dates_str = my_dates_str.replace( ' - ', ', ' ); // FixIn: 10.2.3.2. | |
| 323 | 589 | } |
| 324 | - return false; | |
| 325 | - } | |
| 326 | 590 | |
| 327 | - | |
| 328 | - function checkTimeInside( mytime, is_start_time, bk_type ){ | |
| 329 | - | |
| 330 | - var my_dates_str = document.getElementById( 'date_booking' + bk_type ).value; // GET DATES From TEXTAREA | |
| 331 | - | |
| 332 | 591 | return checkTimeInsideProcess( mytime, is_start_time, bk_type, my_dates_str ); |
| 333 | - | |
| 334 | 592 | } |
| 335 | 593 | |
| 336 | - | |
| 337 | 594 | function checkRecurentTimeInside( my_rangetime, bk_type ){ |
| 338 | 595 | |
| 339 | 596 | var valid_time = true; |
| 340 | 597 | var my_dates_str = document.getElementById( 'date_booking' + bk_type ).value; // GET DATES From TEXTAREA |
| @@ -356,14 +613,16 @@ | ||
| 356 | 613 | |
| 357 | 614 | return valid_time; |
| 358 | 615 | } |
| 359 | 616 | |
| 360 | - | |
| 361 | -// Function check start and end time at selected days | |
| 617 | + // Function check start and end time at selected days. | |
| 362 | 618 | function checkTimeInsideProcess( mytime, is_start_time, bk_type, my_dates_str ){ |
| 363 | - var i, h, s, m; //FixIn: 9.1.5.1 | |
| 619 | + var i, h, s, m; // FixIn: 9.1.5.1. | |
| 364 | 620 | |
| 365 | - var date_array = my_dates_str.split( ", " ); | |
| 621 | + var date_array = my_dates_str.split( ',' ); | |
| 622 | + date_array = date_array.map( function (s) { | |
| 623 | + return s.trim(); | |
| 624 | + } ); | |
| 366 | 625 | if ( date_array.length == 2 ){ // This recheck is need for editing booking, with single day |
| 367 | 626 | if ( date_array[ 0 ] == date_array[ 1 ] ){ |
| 368 | 627 | date_array = [ date_array[ 0 ] ]; |
| 369 | 628 | } |
| @@ -384,13 +643,14 @@ | ||
| 384 | 643 | for ( i = 0; i < sort_date_array.length; i++ ){ // trnasform to integers |
| 385 | 644 | sort_date_array[ i ] = [ parseInt( sort_date_array[ i ][ 0 ] * 1 ), parseInt( sort_date_array[ i ][ 1 ] * 1 ), parseInt( sort_date_array[ i ][ 2 ] * 1 ) ]; // [2009,7,1],... |
| 386 | 645 | } |
| 387 | 646 | |
| 388 | - if ( ((is_check_start_time_gone) && (is_start_time)) || | |
| 389 | - ((!is_check_start_time_gone) && (!is_start_time)) ){ | |
| 647 | + if ( is_start_time ) { | |
| 648 | + if ( wpbc_is_time_in_the_past_for_today( mytime, sort_date_array, bk_type ) ) { | |
| 649 | + return false; | |
| 650 | + } | |
| 651 | + } | |
| 390 | 652 | |
| 391 | - if ( isTimeTodayGone( mytime, sort_date_array ) ) return false; | |
| 392 | - } | |
| 393 | 653 | // CHECK FOR BOOKING INSIDE OF S E L E C T E D DAY RANGE AND FOR TOTALLY BOOKED DAYS AT THE START AND END OF RANGE |
| 394 | 654 | work_date_array = sort_date_array; |
| 395 | 655 | for ( var j = 0; j < work_date_array.length; j++ ){ |
| 396 | 656 | td_class = work_date_array[ j ][ 1 ] + '-' + work_date_array[ j ][ 2 ] + '-' + work_date_array[ j ][ 0 ]; |
| @@ -511,39 +771,7 @@ | ||
| 511 | 771 | else { |
| 512 | 772 | if ( start_time_checking_index != undefined ) |
| 513 | 773 | if ( start_time_checking_index[ 2 ] != undefined ) |
| 514 | 774 | if ( (sort_date_array.length == 1) && (start_time_checking_index[ 2 ] >= mytime_value) ) return false; // we are select only one day and end time is earlythe starttime its wrong |
| 515 | - } | |
| 516 | - return true; | |
| 517 | - } | |
| 518 | - | |
| 519 | - | |
| 520 | - //PS: This function from ../booking/inc/js/personal.js | |
| 521 | - function isValidTimeTextField( timeStr ){ | |
| 522 | - // Checks if time is in HH:MM AM/PM format. | |
| 523 | - // The seconds and AM/PM are optional. | |
| 524 | - | |
| 525 | - var timePat = /^(\d{1,2}):(\d{2})(\s?(AM|am|PM|pm))?$/; | |
| 526 | - | |
| 527 | - var matchArray = timeStr.match( timePat ); | |
| 528 | - if ( matchArray == null ){ | |
| 529 | - return false; //("<?php _e('Time is not in a valid format. Use this format HH:MM or HH:MM AM/PM'); ?>"); | |
| 530 | - } | |
| 531 | - var hour = matchArray[ 1 ]; | |
| 532 | - var minute = matchArray[ 2 ]; | |
| 533 | - var ampm = matchArray[ 4 ]; | |
| 534 | - | |
| 535 | - if ( ampm == "" ){ | |
| 536 | - ampm = null | |
| 537 | - } | |
| 538 | - | |
| 539 | - if ( hour < 0 || hour > 24 ){ //FixIn: 8.3.1.1 | |
| 540 | - return false; //("<?php _e('Hour must be between 1 and 12. (or 0 and 23 for military time)'); ?>"); | |
| 541 | - } | |
| 542 | - if ( hour > 12 && ampm != null ){ | |
| 543 | - return false; //("<?php _e('You can not specify AM or PM for military time.'); ?>"); | |
| 544 | - } | |
| 545 | - if ( minute < 0 || minute > 59 ){ | |
| 546 | - return false; //("<?php _e('Minute must be between 0 and 59.'); ?>"); | |
| 547 | 775 | } |
| 548 | 776 | return true; |
| 549 | 777 | } |