Auto-select the Only Available Time Slot

When a date is chosen and exactly ONE time slot is available, select it automatically so users don’t miss the extra click. If several slots are available, nothing is auto-selected.

The default selector is ‘.gpb-booking-time-picker__slot’ (the GP Bookings time slot element).

Instructions

  1. Install this snippet: https://gravitywiz.com/documentation/how-do-i-install-a-snippet/
  2. Set ‘form_id’ in the configuration at the bottom. ‘slot_selector’ only needs changing if your markup differs.

If the snippet doesn’t select anything: Pick a date so slots appear, right-click a time slot > Inspect, and confirm the slot element has the class ‘gpb-booking-time-picker__slot’. If it uses a different class, set ‘slot_selector’ to that class.

Code

Filename: gpb-auto-select-only-available-time-slot.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<?php
/**
 * Gravity Perks // Bookings // Auto-select the Only Available Time Slot
 *
 * When a date is chosen and exactly ONE time slot is available, select it automatically so users
 * don't miss the extra click. If several slots are available, nothing is auto-selected.
 *
 * The default selector is '.gpb-booking-time-picker__slot' (the GP Bookings time slot element).
 *
 * Instructions:
 * 1. Install this snippet: https://gravitywiz.com/documentation/how-do-i-install-a-snippet/
 * 2. Set 'form_id' in the configuration at the bottom. 'slot_selector' only needs changing if your markup differs.
 *
 * If the snippet doesn't select anything:
 *   Pick a date so slots appear, right-click a time slot > Inspect, and confirm the slot element has the class
 *   'gpb-booking-time-picker__slot'. If it uses a different class, set 'slot_selector' to that class.
 */
class GPB_Auto_Select_Only_Time_Slot {

	private $_args = array();

	public function __construct( $args = array() ) {

		$this->_args = wp_parse_args( $args, array(
			'form_id'       => 0,
			'slot_selector' => '',
		) );

		add_filter( 'gform_pre_render', array( $this, 'add_init_script' ), 10, 1 );
	}

	public function add_init_script( $form ) {

		if ( (int) $form['id'] !== (int) $this->_args['form_id'] || empty( $this->_args['slot_selector'] ) ) {
			return $form;
		}

		$args = array(
			'formId'       => (int) $this->_args['form_id'],
			'slotSelector' => $this->_args['slot_selector'],
		);

		$script = 'new GPBAutoSelectOnlyTimeSlot( ' . wp_json_encode( $args ) . ' );';
		$slug   = 'gpb_auto_select_only_time_slot_' . $args['formId'];

		if ( class_exists( 'GFFormDisplay' ) ) {
			GFFormDisplay::add_init_script( $args['formId'], $slug, GFFormDisplay::ON_PAGE_RENDER, $script );
		}

		if ( ! has_action( 'wp_footer', array( $this, 'output_script' ) ) ) {
			add_action( 'wp_footer', array( $this, 'output_script' ) );
			add_action( 'gform_preview_footer', array( $this, 'output_script' ) );
		}

		return $form;
	}

	public function output_script() {
		?>
		<script type="text/javascript">
			window.GPBAutoSelectOnlyTimeSlot = function ( args ) {

				var wrapper = document.getElementById( 'gform_wrapper_' + args.formId );
				if ( ! wrapper || wrapper.getAttribute( 'data-gpb-autoselect' ) ) {
					return;
				}
				wrapper.setAttribute( 'data-gpb-autoselect', '1' );

				function isAvailable( el ) {
					if ( el.disabled || el.getAttribute( 'aria-disabled' ) === 'true' ) {
						return false;
					}
					if ( /\b(disabled|unavailable|booked|full)\b/i.test( el.className ) ) {
						return false;
					}
					// Visible on screen.
					return !! ( el.offsetWidth || el.offsetHeight || el.getClientRects().length );
				}

				function isSelected( el ) {
					return el.checked === true
						|| el.getAttribute( 'aria-pressed' ) === 'true'
						|| el.getAttribute( 'aria-checked' ) === 'true'
						|| el.getAttribute( 'aria-selected' ) === 'true'
						|| /\b(selected|active|checked)\b/i.test( el.className );
				}

				function run() {
					var slots = Array.prototype.slice.call( wrapper.querySelectorAll( args.slotSelector ) );
					var available = slots.filter( isAvailable );

					if ( available.length !== 1 ) {
						return;
					}

					var slot = available[ 0 ];

					// Already selected, or already auto-selected once (do not re-click if the user changes it).
					if ( isSelected( slot ) || slot.getAttribute( 'data-gpb-autoselected' ) ) {
						return;
					}

					slot.setAttribute( 'data-gpb-autoselected', '1' );
					slot.click();
				}

				// Slots are rendered after a date is picked, so watch for changes and debounce.
				var timer;
				new MutationObserver( function () {
					clearTimeout( timer );
					timer = setTimeout( run, 200 );
				} ).observe( wrapper, { childList: true, subtree: true } );

				run();
			};
		</script>
		<?php
	}
}

# Configuration

new GPB_Auto_Select_Only_Time_Slot( array(
	'form_id'       => 123,
	'slot_selector' => '.gpb-booking-time-picker__slot',
) );

Leave a Reply

Your email address will not be published. Required fields are marked *

  • Trouble installing this snippet? See our troubleshooting tips.
  • Need to include code? Create a gist and link to it in your comment.
  • Reporting a bug? Provide a URL where this issue can be recreated.

By commenting, I understand that I may receive emails related to Gravity Wiz and can unsubscribe at any time.