PageSourceSearch

https://trekkingspessart.de/wp-content/plugins/ph-bookings-appoint…/js/ph-booking-autofill.js?ver=5.1.7

js trekkingspessart.de collected 2026-10-09 00:40:47 UTC 19,270 bytes, 586 lines download raw bytes

1jQuery(window).on('load', function () {
2
3	let searchParams = new URLSearchParams(window.location.search)
4	if (!(searchParams.has('invoker') && searchParams.get('invoker') === 'phbookingsearch')) {
5		return;
6	}
7
8	const isSummaryPage = jQuery('#ph_search_product_view').val() === 'summary' ? true : false;
9
10	const data = {
11		action: 'ph_get_search_params'
12	}
13
14	let productId = jQuery('form.cart #phive_product_id').val();
15	var producData= '';
16	jQuery.post(ph_booking_autofill.ajaxurl, data, function (response) {
17
18		const { search_params } = response?.data || {};
19
20		if (!search_params) {
21			return;
22		}
23
24		let participants = search_params['ph_book_search_participants'];
25		let totalParticipants = 0;
26		participants = participants.replace(/\\/g, "");
27		participants = JSON.parse(participants);
28		let productParticipant = [];
29		// Iterate through each participant section
30		jQuery('.participant_inner_section').each(function (index) {
31		// Find the input field within the current participant section
32
33			var inputField = jQuery(this).find('input.input-person');
34
35			var participantType = inputField.data('name');
36
37			participants.forEach(participant => {
38
39				// Autofill the input field with the corresponding value
40				if (participant.rule == participantType) {
41					inputField.val(participant.count);
42				}
43
44			});
45		});
46
47		//Setting the product page from date in search bar
48		var fromDate = search_params['book_search_from'];
49		jQuery('#ph_book_search_from').val(fromDate);
50
51		//Setting the product page to date in search bar
52		var toDate = search_params['book_search_to'];
53		jQuery('#ph_book_search_to').val(toDate);
54		//Setting the product page participant count for each rule
55		var participantNameCount = '';
56		var hiddenInputsPersons = '';
57		var hiddenInputsRules = '';
58		var hiddenInputsbooking = '';
59
60
61		jQuery('#ph_book_search_number_of_participants_button .ph_participant-group').each(function () {
62
63			let participantRule = jQuery(this).data('participant');
64			let inputField = jQuery(this).find('input[type="number"]');
65
66			participants.forEach(participant => {
67				if (participant.rule === participantRule) {
68					inputField.val(participant.count);
69					totalParticipants += participant.count;
70					if(participant.count > 0) {
71						participantNameCount += `${participant.rule} ${participant.count},  `;
72					}
73					productParticipant.push(participant.count);
74
75					hiddenInputsPersons += `<input type="hidden" name="phive_book_persons[]" class="phive_book_persons" value="${participant.count}">`;
76					hiddenInputsRules += `<input type="hidden" name="ph_person_rule[]" class="ph_person_rule" value="${participant.rule}">`;
77					hiddenInputsbooking = `<input type="hidden" name="persons_as_booking" class="persons_as_booking" value="no">`;
78				}
79			});
80		});
81
82		jQuery('form.cart').append(hiddenInputsPersons);
83		jQuery('form.cart').append(hiddenInputsRules);
84		jQuery('form.cart').append(hiddenInputsbooking);
85
86		hiddenInputsPersons = '';
87		hiddenInputsRules = '';
88		hiddenInputsbooking = '';
89		participantNameCount = participantNameCount.trim().replace(/,$/, '');
90
91		//Setting the product page total participant count in search bar
92		jQuery('#participant_count_display').text(totalParticipants);
93
94		//Setting the product page asset item in search bar
95		let assetId = search_params['ph_search_asset_name'];
96		let assetItem = jQuery('.ph_book_search_asset_item[data-value="' + assetId + '"]'); //#ph_book_search_asset_list 
97		var assetName = '';
98		if (assetItem.length > 0) {
99			assetName = assetItem.attr('title');
100			jQuery('#ph_asset_name').val(assetName);
101			jQuery('#ph_asset_name').attr('data-ph-search-asset-id', assetId);
102		}
103
104		//product summary deatils
105		jQuery(document).ready(function () {
106			setTimeout(function () {
107				if (search_params.book_search_from) {
108					jQuery('#ph_product_from_date').text(search_params.book_search_from);
109					jQuery('label[for="ph_product_from_date_label"]').text(search_params.ph_from_date_text ? search_params.ph_from_date_text + ':' : '').toggle(!!search_params.ph_from_date_text);
110				} else {
111					jQuery('#ph_product_from_date').closest('.ph_product_row').hide();
112				}
113
114				if (search_params.book_search_to) {
115					jQuery('#ph_product_to_date').text(search_params.book_search_to);
116					jQuery('label[for="ph_product_to_date_label"]').text(search_params.ph_to_date_text ? search_params.ph_to_date_text + ':' : '').toggle(!!search_params.ph_to_date_text);
117				} else {
118					jQuery('#ph_product_to_date').closest('.ph_product_row').hide();
119				}
120
121				if (assetName) {
122					jQuery('#ph_product_asset_name').text(assetName);
123					jQuery('label[for="ph_product_asset_name_label"]').text(search_params.ph_asset_label ? search_params.ph_asset_label + ':' : '').toggle(!!search_params.ph_asset_label);
124				} else {
125					jQuery('#ph_product_asset_name').closest('.ph_product_row').hide();
126				}
127
128				if (participantNameCount) {
129					jQuery('#ph_product_participant_name_count').text(participantNameCount);
130					jQuery('label[for="ph_product_participant_label"]').text(search_params.ph_participant_lable ? search_params.ph_participant_lable + ':' : '').toggle(!!search_params.ph_participant_lable);
131				} else {
132					jQuery('#ph_product_participant_name_count').closest('.ph_product_row').hide();
133				}
134				jQuery('label[for="ph_booking_cost_label"]').text('Booking Cost:');
135				jQuery('.ph_outer_container').addClass('loaded');
136			}, 1000);
137		});
138
139		if (search_params.ph_product_view) {
140			jQuery('#ph_product_views').val(search_params.ph_product_view);
141		} else {
142			jQuery('#ph_product_views').closest('.ph_product_row').hide();
143		}
144
145		/**
146		 * Updating hidden fields manually to handle add to cart when using summary page.
147		 */
148
149		// Formatting date for month calendar.
150		if ('month' === jQuery('.book_interval_period').val()) {
151			
152			let dateStr = search_params.book_search_from;
153			let yearAndMonth = moment(dateStr).format("YYYY-MM"); // Format to get "YYYY-MM"
154			
155			jQuery('.ph-date-from').val(yearAndMonth || '');
156			jQuery('.ph-date-to').val(yearAndMonth || '');
157		} 
158		else {
159
160			jQuery('.ph-date-from').val(search_params.book_search_from || '');
161
162			const dateTo = getDatePart(search_params.book_search_to) + ' ' + getTimePart(new Date(search_params.book_search_to), 'to');
163
164			// jQuery('.ph-date-to').val(search_params.book_search_to || '');
165			jQuery('.ph-date-to').val(dateTo);
166		}
167
168		jQuery('.display_time_from').val(search_params.book_search_from);
169    	jQuery('.display_time_to').val(search_params.book_search_to);
170		
171		jQuery('.phive_book_assets').val(assetName || '');
172
173		// Autofill Asset.
174		// When asset is empty considering first available asset.
175		if (!search_params['ph_search_asset_name'] || jQuery('.phive_book_assets option[value="' + search_params['ph_search_asset_name'] + '"]').length == 0 ) {
176			jQuery('.phive_book_assets').prop('selectedIndex', 0);
177		} else {
178			jQuery('.phive_book_assets option[value="' + search_params['ph_search_asset_name'] + '"]').prop('selected', 'true');
179		}
180
181		// Checks whether all dayes of the month aren't bookable.
182		const totalDays 		= jQuery('.ph-calendar-days li').length;
183		const unavailableDays 	= jQuery('.ph-calendar-days li.de-active').length;
184		
185		// Triggering month change to next month.
186		if (totalDays == unavailableDays) {
187			jQuery('.ph-next').trigger('click');
188		}
189
190		setTimeout(() => {
191			checkAndSelect(search_params);
192		}, 500);
193
194		jQuery(document).on('change', '.ph-ul-time', function () {
195
196			jQuery(".ph-ul-time li").each(function () {
197				const date = jQuery(this).find(".callender-full-date").val();
198
199				const time = date.split(' ')[1];
200
201				if (jQuery('.selected-date').length == 0) {
202					if (time == search_params['ph_book_search_range_from'] && !jQuery(this).hasClass('de-active') && !jQuery(this).hasClass('not-available') && !jQuery(this).hasClass('booking-full') && !jQuery(this).hasClass('non-working-time')) {
203						jQuery(this).trigger('click');
204					}
205				}
206			});
207		});
208
209		// Cost calculation to be triggered manually only for summary page.
210		if (isSummaryPage) {
211
212			var addon_data = jQuery('.addon').serialize();
213			if (parseInt(jQuery(".wc-pao-addon-field").length) > 0) {
214				addon_data = jQuery('.wc-pao-addon-field').serialize();
215			}
216	
217			// Handling extra slot at the end for summary page cost calculation.
218			const intervalPeriod = jQuery('.book_interval_period').val();
219
220			if (search_params['ph_book_search_filter_date_and_time'] && ['hour', 'minute'].includes(intervalPeriod)) {
221				const dateTime = new Date(toDate);
222				toDate = getDatePart(toDate) + ' ' + getTimePart(dateTime, 'to');
223			}
224	
225			var producData = {
226				action: 'phive_get_booked_price',
227				// security : phive_booking_ajax.security,
228				product_id: productId,
229				book_from: fromDate,
230				book_to: toDate,
231				person_details: productParticipant,
232				asset: assetId,
233				addon_data: addon_data,
234				autofill: 'autofill-summary'
235			};
236	
237			var result = '';
238			jQuery.post(ph_booking_autofill.ajaxurl, producData, function (res) {
239				result = jQuery.parseJSON(res);
240				setTimeout(() => {
241					jQuery('#ph_booking_cost').html(result.price_html);
242				}, 1000);
243			});
244		}
245
246	});
247
248	function checkAndSelect(search_params) {
249
250		let isDateFound = false;
251
252		// For date part, we have to match pattern according to widget settings.
253		let searchFromDateTime	= search_params['book_search_from'];
254		let searchToDateTime	= search_params['book_search_to'];
255	
256		const fromDate	= getDatePart(searchFromDateTime);
257		const toDate	= getDatePart(searchToDateTime);
258
259		searchFromDateTime	= new Date(search_params['book_search_from']);
260		searchToDateTime	= new Date(search_params['book_search_to']);
261
262		const fromTime		= getTimePart(searchFromDateTime);
263		const toTime		= getTimePart(searchToDateTime, 'to');
264		const across_day	= jQuery('.across_the_day_booking').val();
265		const interval_period = jQuery('.book_interval_period').val();
266
267		// When searched for Range calendar.
268		if (!search_params['ph_fixed_date']) {
269
270			// For month calendar
271			if ('month' == interval_period) {
272				
273				const monthFromDate	= new Date(fromDate);
274				const monthFromYear	= monthFromDate.getFullYear();
275				const monthFrom		= (monthFromDate.getMonth() + 1).toString().padStart(2, '0');
276
277				// Combine year and month
278				const fromYearMonth = `${monthFromYear}-${monthFrom}`;
279
280				const monthToDate	= new Date(toDate);
281				const monthToYear	= monthToDate.getFullYear();
282				const monthTo		= (monthToDate.getMonth() + 1).toString().padStart(2, '0');
283
284				// Combine year and month
285				const toYearMonth = `${monthToYear}-${monthTo}`;
286
287				jQuery(".ph-calendar-days li").each(function () {
288					const date = jQuery(this).find(".callender-full-date").val();
289
290					if (fromYearMonth == date && !jQuery(this).hasClass('de-active')) {
291						jQuery(this).trigger('click');
292		
293						jQuery(".ph-calendar-days li").each(function () {
294							const date = jQuery(this).find(".callender-full-date").val();
295		
296							if (fromYearMonth != toYearMonth && toYearMonth == date && !jQuery(this).hasClass('de-active')) {
297								setTimeout(() => {
298									jQuery(this).trigger('click');
299								}, 1000);
300							}
301						});
302					}
303				});
304			}
305
306			jQuery(".ph-calendar-days li").each(function () {
307
308				const date = jQuery(this).find(".callender-full-date").val();
309				if (
310					date == fromDate
311					&& !jQuery(this).hasClass('temporary-unavailable')
312					&& !jQuery(this).hasClass('ph-next-month-date')
313				) {
314					isDateFound = true;
315					jQuery(this).trigger('click');
316
317					// When across day booking is enabled and searched for time calendar.
318					if ('yes' == across_day && search_params['ph_book_search_filter_date_and_time']) {
319						
320						// Select the from time.
321						if (fromTime) {
322							selectFromTime(fromDate, fromTime);
323						}
324
325						// Calculate the range difference and trigger next day click.
326						const count = calculateRangeDifference(fromDate, toDate);
327
328						function triggerClickWithDelay(index) {
329
330							// Trigger next day click until the range is met.
331							if (index < count) {
332								setTimeout(function() {
333									// Trigger the click
334									jQuery('.ph-next-day-time').trigger('click');
335
336									// Call the next iteration
337									triggerClickWithDelay(index + 1);
338								}, 1000);
339							} else {
340								// Else condition triggers when all the across day clicks are done, so now we can trigger time selection.
341								if (toTime) {
342									selectToTime(toDate, toTime, count);
343								}
344							}
345						}
346
347						// Start the loop from index 0
348						setTimeout(() => {
349							triggerClickWithDelay(0);
350						}, 1000);
351					}
352				}
353
354				if (date == toDate && (!fromTime || !search_params['ph_book_search_filter_date_and_time'])) {
355					setTimeout(() => {
356						jQuery(this).trigger('click');
357					}, 1000);
358				}
359			});
360		} 
361		// When searched for Fixed calendar
362		else {
363
364			// For month calendar
365			if ('month' == interval_period) {
366				
367				const date	= new Date(fromDate);
368				const year	= date.getFullYear();
369				const month = (date.getMonth() + 1).toString().padStart(2, '0');
370
371				// Combine year and month
372				const yearMonth = `${year}-${month}`;
373
374				jQuery(".ph-calendar-days li").each(function () {
375					const date = jQuery(this).find(".callender-full-date").val();
376	
377					if (yearMonth == date && !jQuery(this).hasClass('de-active')) {
378						jQuery(this).trigger('click');
379					}
380				});
381			} else {
382
383				// For calendars other than month.
384				jQuery(".ph-calendar-days li").each(function () {
385					const date = jQuery(this).find(".callender-full-date").val();
386	
387					if (
388						date == fromDate
389						&& !jQuery(this).hasClass('temporary-unavailable')
390						&& !jQuery(this).hasClass('ph-next-month-date')
391					) {
392						isDateFound = true;
393						jQuery(this).trigger('click');
394					}
395				});
396			}
397		}
398
399		// When from date isn't bookable, move to next month and do the search.
400		if (!isDateFound && 'month' != interval_period) {
401			jQuery('.ph-next').trigger('click');
402			setTimeout(() => {
403				checkAndSelect(search_params);
404			}, 500);
405		}
406
407		if (across_day == 'no' || search_params['ph_fixed_date']) {
408			
409			// From time selection.
410			if (fromTime) {
411				selectFromTime(fromDate, fromTime);
412			}
413
414			// To time selection.
415			if (toTime) {
416				selectToTime(toDate, toTime);
417			}
418		}
419	}
420
421	/**
422	 * Get time part from given dateTime.
423	 */
424	function getTimePart(dateTime, type = '') {
425
426		// Handling extra slot at the end.
427		if ('to' == type) {
428			const interval = jQuery('.book_interval').val();
429			const intervalPeriod = jQuery('.book_interval_period').val();
430			const isFixedDateSearch = jQuery('#ph_fixed_date').val();
431			
432			// Extra slots get added only for range search.
433			if ('minute' === intervalPeriod && !isFixedDateSearch) {
434				dateTime.setMinutes(dateTime.getMinutes() - interval);
435			}
436
437			if ('hour' === intervalPeriod && !isFixedDateSearch) {
438				dateTime.setHours(dateTime.getHours() - interval);
439			}
440		}
441
442		// Extract the hours and minutes
443		let hours = dateTime.getHours().toString().padStart(2, "0");
444		let minutes = dateTime.getMinutes().toString().padStart(2, "0");
445
446		// Format the time in "HH:MM" format
447		let fromTime = (hours === 0 && minutes === "00") ? null : `${hours}:${minutes}`;
448
449		return fromTime;
450	}
451
452	/**
453	 * Get date part from given dateTime.
454	 */
455	function getDatePart(inputDate) {
456
457		const patterns = [
458			{ 
459				pattern: /^(?<day>\d{2})-(?<month>\d{2})-(?<year>\d{4})(?: (?<hours>\d{2}):(?<minutes>\d{2}) (?<period>AM|PM))?$/, 
460				format: 'dd-mm-yy' 
461			},
462			{ 
463				pattern: /^(?<day>\d{2})\/(?<month>\d{2})\/(?<year>\d{4})(?: (?<hours>\d{2}):(?<minutes>\d{2}) (?<period>AM|PM))?$/, 
464				format: 'dd/mm/yy' 
465			},
466			{ 
467				pattern: /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})(?: (?<hours>\d{2}):(?<minutes>\d{2}) (?<period>AM|PM))?$/, 
468				format: 'yy-mm-dd' 
469			},
470			{ 
471				pattern: /^(?<year>\d{4})\/(?<month>\d{2})\/(?<day>\d{2})(?: (?<hours>\d{2}):(?<minutes>\d{2}) (?<period>AM|PM))?$/, 
472				format: 'yy/mm/dd' 
473			}
474		];
475		
476
477        for (const { pattern } of patterns) {
478            const match = inputDate.match(pattern);
479            if (match) {
480                const { groups } = match;
481                const year = groups.year;
482                const month = groups.month;
483                const day = groups.day;
484                const hours = groups.hours;
485                const minutes = groups.minutes;
486                const time = hours && minutes ? ` ${hours}:${minutes}` : '';
487                
488                return `${year}-${month}-${day}`;
489            }
490        }
491
492        return null;
493	}
494
495	/**
496	 * Get date range difference.
497	 */
498	function calculateRangeDifference(fromDate, toDate) {
499
500		let dateFrom = new Date(fromDate);
501		let dateTo = new Date(toDate);
502
503		// Calculate the difference in time.
504		let timeDifference = dateTo - dateFrom;
505
506		// Convert time difference to days
507		let dayDifference = timeDifference / (1000 * 60 * 60 * 24);
508
509		return dayDifference;
510	}
511
512	/**
513	 * Select from time.
514	 */
515	function selectFromTime(fromDate, fromTime) {
516
517		// Flag to ensure that click is triggered once.
518		var isFromClicked = false;
519
520		jQuery(document).on('change', '.ph-ul-time', function () {
521
522			jQuery(".ph-ul-time li").each(function () {
523				const date = jQuery(this).find(".callender-full-date").val();
524				const nextDate = jQuery(this).next().find(".callender-full-date").val();
525
526				const frmdate = date.split(' ')[0].trim();
527				const time = date.split(' ')[1].trim();
528				
529				const nextTimeSlot = nextDate ? nextDate.split(' ')[1] : '';
530
531				if (jQuery('.selected-date').length == 0) {
532					if (fromDate == frmdate && time == fromTime && !jQuery(this).hasClass('de-active') && !jQuery(this).hasClass('not-available') && !jQuery(this).hasClass('booking-full') && !jQuery(this).hasClass('non-working-time')) {
533						isFromClicked = true;
534						jQuery(this).trigger('click');
535					} else if ( fromTime >= time && fromTime < nextTimeSlot && !isFromClicked) { // When exact slot isn't available
536						jQuery(this).trigger('click');
537					}
538				}
539			});
540		});
541	}
542	
543
544	/**
545	 * Select to time based on same day or range of days.
546	 */
547	function selectToTime(toDate, toTime, count) {
548
549		// When count is zero, it means selection is for same day, hence for same day ph-ul-time trigger won't happen
550		if (count === 0) {
551			toTimeSelection(toTime);
552		} else {
553			jQuery(document).on('change', '.ph-ul-time', function () {
554				toTimeSelection(toTime)
555			});
556		}
557	}
558
559	/**
560	 * Select to time.
561	 */
562	function toTimeSelection(toTime) {
563
564		// Flag to ensure that click is triggered once.
565		var isToClicked = false;
566
567		jQuery(".ph-ul-time li").each(function () {
568	
569			const date = jQuery(this).find(".callender-full-date").val();
570			const nextDate = jQuery(this).next().find(".callender-full-date").val();
571
572			const nextTimeSlot = nextDate ? nextDate.split(' ')[1] : '';
573
574			const time = date.split(' ')[1].trim();
575			
576			if (time == toTime && !jQuery(this).hasClass('de-active') && !jQuery(this).hasClass('not-available') && !jQuery(this).hasClass('booking-full') && !jQuery(this).hasClass('non-working-time')) {
577					isToClicked = true;
578					setTimeout(() => {
579						jQuery(this).trigger('click');
580					}, 1000);
581				} else if (toTime >= time && toTime < nextTimeSlot && !isToClicked) { // When exact slot isn't available
582					jQuery(this).trigger('click');
583				}
584		});
585	}
586});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.