PluginProbe
Booking Calendar / 11.2
Booking Calendar v11.2
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
booking / includes / page-form-builder / field-packs / time-end / field-endtime-wptpl.php

field-endtime-wptpl.php in Booking Calendar 11.2, at includes/page-form-builder/field-packs/time-end/field-endtime-wptpl.php

583 lines 30.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WPBC BFB Pack: End Time (single time points).
4 *
5 * - Adds an "endtime" field that renders dropdown options like:
6 * [selectbox endtime "08:00" "09:00" ... ]
7 * - Labels can be AM/PM or 24h; values are always strict "HH:MM" (24h).
8 * - Inspector:
9 * - AM/PM </> 24H switch (radio)
10 * - Generator: From/To + Duration (step) -> builds single time points
11 * - Options editor with rows that mirror the chosen format
12 * - Respects global "Show as time picker" toggle used by time-based fields.
13 * - Requires iMask.js (already loaded on the Builder page) for 24h masking.
14 *
15 * @package Booking Calendar
16 * @author wpdevelop
17 * @since 11.0.0
18 * @modified 01.11.2025
19 * @version 1.0.0
20 */
21
22 if ( ! defined( 'ABSPATH' ) ) {
23 exit;
24 }
25
26 /**
27 * Register the "endtime" field pack.
28 *
29 * @param array $packs Packs map.
30 * @return array
31 */
32 function wpbc_bfb_register_field_packs__field_endtime_wptpl( $packs ) {
33 $packs['endtime'] = array(
34 'kind' => 'field',
35 'type' => 'endtime',
36 'label' => __( 'End time', 'booking' ),
37 'icon' => 'wpbc-bi-clock',
38 'usage_key' => 'endtime',
39
40 'schema' => array(
41 'props' => array(
42 'label' => array( 'type' => 'string', 'default' => __( 'End time', 'booking' ) ),
43 'name' => array( 'type' => 'string', 'default' => 'endtime' ),
44 'html_id' => array( 'type' => 'string', 'default' => '' ),
45 'required' => array( 'type' => 'boolean', 'default' => true ),
46 'multiple' => array( 'type' => 'boolean', 'default' => false ),
47 'size' => array( 'type' => 'number', 'default' => null, 'min' => 2, 'max' => 20 ),
48 'cssclass' => array( 'type' => 'string', 'default' => '' ),
49 'help' => array( 'type' => 'string', 'default' => '' ),
50 'default_value' => array( 'type' => 'string', 'default' => '' ),
51 'placeholder' => array( 'type' => 'string', 'default' => '--- ' . __( 'Select time', 'booking' ) . ' ---' ),
52 'value_differs' => array( 'type' => 'boolean', 'default' => true ),
53
54 // AM/PM labels, 24h values.
55 'options' => array(
56 'type' => 'array',
57 'default' => array(
58 array( 'label' => '08:00 AM', 'value' => '08:00', 'selected' => false ),
59 array( 'label' => '09:00 AM', 'value' => '09:00', 'selected' => false ),
60 array( 'label' => '10:00 AM', 'value' => '10:00', 'selected' => false ),
61 array( 'label' => '11:00 AM', 'value' => '11:00', 'selected' => false ),
62 array( 'label' => '12:00 PM', 'value' => '12:00', 'selected' => false ),
63 array( 'label' => '01:00 PM', 'value' => '13:00', 'selected' => false ),
64 array( 'label' => '02:00 PM', 'value' => '14:00', 'selected' => false ),
65 array( 'label' => '03:00 PM', 'value' => '15:00', 'selected' => false ),
66 array( 'label' => '04:00 PM', 'value' => '16:00', 'selected' => false ),
67 array( 'label' => '05:00 PM', 'value' => '17:00', 'selected' => false ),
68 array( 'label' => '06:00 PM', 'value' => '18:00', 'selected' => false ),
69 array( 'label' => '07:00 PM', 'value' => '19:00', 'selected' => false ),
70 array( 'label' => '08:00 PM', 'value' => '20:00', 'selected' => false ),
71 array( 'label' => '09:00 PM', 'value' => '21:00', 'selected' => false ),
72 array( 'label' => '10:00 PM', 'value' => '22:00', 'selected' => false ),
73 ),
74 ),
75
76 // Generator defaults -> AM/PM initially.
77 'gen_label_fmt' => array( 'type' => 'string', 'default' => 'ampm' ), // 'ampm' | '24h'
78 'gen_start_24h' => array( 'type' => 'string', 'default' => '08:00' ),
79 'gen_end_24h' => array( 'type' => 'string', 'default' => '22:00' ),
80 'gen_start_ampm_t' => array( 'type' => 'string', 'default' => '08:00' ),
81 'gen_end_ampm_t' => array( 'type' => 'string', 'default' => '22:00' ),
82 'gen_step_h' => array( 'type' => 'number', 'default' => 1, 'min' => 0, 'max' => 12 ),
83 'gen_step_m' => array( 'type' => 'number', 'default' => 0, 'min' => 0, 'max' => 59 ),
84
85 'min_width' => array( 'type' => 'string', 'default' => '180px' ),
86 ),
87 ),
88
89 'templates_printer' => 'wpbc_bfb_field_endtime_wptpl_print_templates',
90 );
91
92 return $packs;
93 }
94 add_filter( 'wpbc_bfb_register_field_packs', 'wpbc_bfb_register_field_packs__field_endtime_wptpl' );
95
96 /**
97 * Palette item defaults — AM/PM labels, 24h values.
98 *
99 * @param string $group Group key.
100 * @param string $position Position key.
101 * @return void
102 */
103 function wpbc_bfb_palette_register_items__endtime_wptpl( $group, $position ) {
104 if ( 'times' !== $group || 'bottom' !== $position ) {
105 return;
106 }
107
108 $default_options = array(
109 array( 'label' => '08:00 AM', 'value' => '08:00', 'selected' => false ),
110 array( 'label' => '09:00 AM', 'value' => '09:00', 'selected' => false ),
111 array( 'label' => '10:00 AM', 'value' => '10:00', 'selected' => false ),
112 array( 'label' => '11:00 AM', 'value' => '11:00', 'selected' => false ),
113 array( 'label' => '12:00 PM', 'value' => '12:00', 'selected' => false ),
114 array( 'label' => '01:00 PM', 'value' => '13:00', 'selected' => false ),
115 array( 'label' => '02:00 PM', 'value' => '14:00', 'selected' => false ),
116 array( 'label' => '03:00 PM', 'value' => '15:00', 'selected' => false ),
117 array( 'label' => '04:00 PM', 'value' => '16:00', 'selected' => false ),
118 array( 'label' => '05:00 PM', 'value' => '17:00', 'selected' => false ),
119 array( 'label' => '06:00 PM', 'value' => '18:00', 'selected' => false ),
120 array( 'label' => '07:00 PM', 'value' => '19:00', 'selected' => false ),
121 array( 'label' => '08:00 PM', 'value' => '20:00', 'selected' => false ),
122 array( 'label' => '09:00 PM', 'value' => '21:00', 'selected' => false ),
123 array( 'label' => '10:00 PM', 'value' => '22:00', 'selected' => false ),
124 );
125 ?>
126 <li class="wpbc_bfb__field"
127 data-id="endtime"
128 data-type="endtime"
129 data-usage_key="endtime"
130 data-usagenumber="1"
131 data-min_width="180px"
132 data-label="<?php echo esc_attr( __( 'End time', 'booking' ) ); ?>"
133 data-name="endtime"
134 data-required="true"
135 data-autoname="0"
136 data-fresh="0"
137 data-name_user_touched="1"
138 data-options="<?php echo esc_attr( wp_json_encode( $default_options ) ); ?>">
139 <i class="menu_icon icon-1x wpbc_icn_update"></i>
140 <span class="wpbc_bfb__field-label"><?php echo esc_html( __( 'End time', 'booking' ) ); ?></span>
141 <span class="wpbc_bfb__field-type">endtime</span>
142 </li>
143 <?php
144 }
145 add_action( 'wpbc_bfb_palette_register_items', 'wpbc_bfb_palette_register_items__endtime_wptpl', 10, 2 );
146
147 /**
148 * Enqueue the End Time pack JS.
149 *
150 * @param string $page Current admin page slug.
151 * @return void
152 */
153 function wpbc_bfb_enqueue__field_endtime_wptpl_js( $page ) {
154 // iMask.js is already enqueued on this page.
155 wp_enqueue_script(
156 'wpbc-bfb_field_endtime_wptpl',
157 wpbc_plugin_url( '/includes/page-form-builder/field-packs/time-end/_out/field-endtime-wptpl.js' ),
158 array( 'wp-util', 'wpbc-bfb', 'wpbc-bfb-time-utils' ),
159 WP_BK_VERSION_NUM,
160 true
161 );
162 }
163 add_action( 'wpbc_enqueue_js_field_pack', 'wpbc_bfb_enqueue__field_endtime_wptpl_js', 10, 1 );
164
165 /**
166 * Print wp.template() blocks (Preview + Inspector) for End Time.
167 *
168 * @param string $page Builder page slug.
169 * @return void
170 */
171 function wpbc_bfb_field_endtime_wptpl_print_templates( $page ) {
172
173 if ( WPBC_BFB_BUILDER_PAGE_SLUG !== $page ) {
174 return;
175 }
176
177 ?>
178 <script type="text/html" id="tmpl-wpbc-bfb-field-endtime">
179 <span class="wpbc_bfb__noaction wpbc_bfb__no-drag-zone" inert="" style="min-width: {{ data.min_width || '180px' }}">
180 <# var is_req = ( true === data.required || 'true' === data.required || 1 === data.required || '1' === data.required ); #>
181
182 <# if ( data.label && data.label !== '' ) { #>
183 <label class="wpbc_bfb__field-label" <# if ( data.html_id ) { #> for="{{ data.html_id }}" <# } #>>
184 {{ data.label }} <# if ( is_req ) { #><span aria-hidden="true">*</span><# } #>
185 </label>
186 <# } #>
187
188 <span class="wpbc_wrap_text wpdev-form-control-wrap">
189 <select
190 class="wpbc_bfb__preview-input wpbc_bfb__preview-select wpbc_bfb__preview-endtime wpbc_bfb__preview-timepicker {{ data.cssclass || '' }}"
191 name="{{ (data.name || data.id || 'endtime') }}"
192 tabindex="-1" aria-disabled="true"
193 <# if ( data.html_id ) { #> id="{{ data.html_id }}" <# } #>
194 <# if ( is_req ) { #> required aria-required="true" <# } #>
195 >
196 <#
197 var has_marked = Array.isArray( data.options ) && data.options.some( function(o){
198 return !! o && ( true === o.selected || 'true' === o.selected || 1 === o.selected || '1' === o.selected );
199 } );
200 var has_text_default = ( (data.default_value != null) && String( data.default_value ).trim() !== '' );
201 var has_any_default = has_marked || has_text_default;
202
203 var selected_set = {};
204 if ( has_marked ) {
205 ( data.options || [] ).forEach( function(o){
206 if ( o && ( true === o.selected || 'true' === o.selected || 1 === o.selected || '1' === o.selected ) ) {
207 selected_set[ String( o.value || '' ) ] = true;
208 }
209 } );
210 } else if ( has_text_default ) {
211 selected_set[ String( data.default_value ) ] = true;
212 }
213 #>
214
215 <# if ( data.placeholder && ! has_any_default ) { #>
216 <option value="" selected="selected" disabled="disabled">{{ data.placeholder }}</option>
217 <# } #>
218
219 <#
220 var _opts = Array.isArray( data.options ) ? data.options
221 : ( function(o){ var a=[],k; for ( k in (o||{}) ){ if ( Object.prototype.hasOwnProperty.call(o,k) ){ a.push( o[k] ); } } return a; } )( data.options );
222 _opts.forEach( function( opt ){
223 if ( ! opt ) { return; }
224 var _val = String( opt.value || '' );
225 var _lbl = String( opt.label || '' );
226 var _sel = !! selected_set[ _val ];
227 #>
228 <option value="{{ _val }}" <# if ( _sel ) { #> selected <# } #> >{{ _lbl }}</option>
229 <# }); #>
230 </select>
231 </span>
232
233 <# if ( data.help ) { #>
234 <div class="wpbc_bfb__help">{{ data.help }}</div>
235 <# } #>
236 </span>
237 </script>
238
239 <script type="text/html" id="tmpl-wpbc-bfb-inspector-endtime">
240 <style type="text/css">
241 .wpbc_admin .wpbc_ui_el__vert_right_bar__wrapper:has(.wpbc_bfb__inspector_timepicker) {
242 --wpbc_ui_left_vert_nav__width_max: Min(580px, 100%);
243 }
244 </style>
245 <!--
246 NOTE:
247 We intentionally include the class "wpbc_bfb__inspector_starttime" here
248 to **reuse** the Start Time pack's delegated JS event handlers
249 (generator, options editor, masks, etc.) without duplicating code.
250 This panel is still unique via "wpbc_bfb__inspector_endtime".
251 -->
252 <div class="wpbc_bfb__inspector_endtime wpbc_bfb__inspector_timepicker wpbc_bfb__inspector_starttime" data-type="endtime"
253 data-i18n-add="<?php echo esc_attr__( 'Add New', 'booking' ); ?>"
254 data-i18n-duplicate="<?php echo esc_attr__( 'Duplicate', 'booking' ); ?>"
255 data-i18n-remove="<?php echo esc_attr__( 'Remove', 'booking' ); ?>"
256 data-i18n-default="<?php echo esc_attr__( 'Default', 'booking' ); ?>"
257 data-i18n-reorder="<?php echo esc_attr__( 'Drag to reorder', 'booking' ); ?>"
258 data-i18n-rowlabel="<?php echo esc_attr__( 'Label (e.g. 05:00 PM)', 'booking' ); ?>"
259 >
260 <div class="wpbc_bfb__inspector__head">
261 <div class="header_container">
262 <div class="header_title_content">
263 <h3 class="title"><?php echo esc_html__( 'End time', 'booking' ); ?></h3>
264 <div class="desc"><?php echo esc_html__( 'Use the generator to quickly create time points.', 'booking' ); ?></div>
265 </div>
266 <div class="actions wpbc_ajx_toolbar wpbc_no_borders">
267 <div class="ui_container ui_container_small">
268 <div class="ui_group">
269 <div class="ui_element">
270 <button type="button" class="button button-secondary wpbc_ui_control wpbc_ui_button" data-action="deselect" aria-label="<?php echo esc_attr__( 'Deselect', 'booking' ); ?>">
271 <i class="menu_icon icon-1x wpbc_icn_remove_done"></i>
272 </button>
273 <button type="button" class="button button-secondary wpbc_ui_control wpbc_ui_button" data-action="scrollto" aria-label="<?php echo esc_attr__( 'Scroll to field', 'booking' ); ?>">
274 <i class="menu_icon icon-1x wpbc_icn_ads_click filter_center_focus"></i>
275 </button>
276 </div>
277 <div class="ui_element">
278 <button type="button" class="button button-secondary wpbc_ui_control wpbc_ui_button" data-action="move-up" aria-label="<?php echo esc_attr__( 'Move up', 'booking' ); ?>">
279 <i class="menu_icon icon-1x wpbc_icn_arrow_upward"></i>
280 </button>
281 <button type="button" class="button button-secondary wpbc_ui_control wpbc_ui_button" data-action="move-down" aria-label="<?php echo esc_attr__( 'Move down', 'booking' ); ?>">
282 <i class="menu_icon icon-1x wpbc_icn_arrow_downward"></i>
283 </button>
284 </div>
285 <div class="ui_element">
286 <button data-action="delete" aria-label="<?php echo esc_attr__( 'Delete', 'booking' ); ?>" type="button" class="button button-secondary wpbc_ui_control wpbc_ui_button wpbc_ui_button_danger button-link-delete">
287 <span class="in-button-text"><?php echo esc_html__( 'Delete', 'booking' ); ?></span>&nbsp;&nbsp;<i class="menu_icon icon-1x wpbc_icn_delete_outline"></i>
288 </button>
289 </div>
290 </div><!-- .ui_group -->
291 </div><!-- .ui_container -->
292 </div><!-- .actions -->
293
294 <?php if ( ! function_exists( 'wpbc_is_mu_user_can_be_here' ) || wpbc_is_mu_user_can_be_here( 'only_super_admin' ) ) { ?>
295 <div class="wpbc_ui__collapsible_group" style="width: 99%;">
296 <div class="inspector__row row__bordered" style="background:#f8f8f8;border:0;justify-content: space-between;">
297 <label class="inspector__label"><?php echo esc_html__( 'Show as time picker', 'booking' ); ?></label>
298 <div class="inspector__control" style="flex: 0 1 auto;">
299 <input type="checkbox" class="inspector__checkbox js-toggle-timeslot-picker">
300 <p class="wpbc_bfb__help" style="margin-top:6px;">
301 <?php echo esc_html__( 'Toggle between selectbox and clickable time slots.', 'booking' ); ?>
302 </p>
303 </div>
304 <?php
305 $opt_name = 'booking_timeslot_picker';
306 $nonce_action = 'wpbc_nonce_' . $opt_name;
307 ?>
308 <a href="javascript:void(0);"
309 class="button button-secondary"
310 onclick="wpbc_save_option_from_element(this);"
311 data-wpbc-u-save-name="<?php echo esc_attr( $opt_name ); ?>"
312 data-wpbc-u-save-nonce="<?php echo esc_attr( wp_create_nonce( $nonce_action ) ); ?>"
313 data-wpbc-u-save-action="<?php echo esc_attr( $nonce_action ) ; ?>"
314 data-wpbc-u-save-value-from=".wpbc_bfb__inspector_timepicker .js-toggle-timeslot-picker"
315 data-wpbc-u-autosave-on-form-save="1"
316 data-wpbc-u-busy-text="<?php esc_attr_e( 'Saving', 'booking' ); ?>...">
317 <?php esc_html_e( 'Save Toggle', 'booking' ); ?>
318 </a>
319 </div>
320 </div>
321 <?php } ?>
322
323 </div><!-- .header_container -->
324 </div><!-- .wpbc_bfb__inspector__head -->
325
326 <div class="wpbc_bfb__inspector__body">
327
328 <section class="wpbc_bfb__inspector__group wpbc_ui__collapsible_group" data-group="basic">
329 <button type="button" class="group__header">
330 <h3><?php echo esc_html__( 'Basic', 'booking' ); ?></h3>
331 <i class="wpbc_ui_el__vert_menu_root_section_icon menu_icon icon-1x wpbc-bi-chevron-right"></i>
332 </button>
333 <div class="group__fields">
334 <div class="inspector__row">
335 <label class="inspector__label"><?php echo esc_html__( 'Label', 'booking' ); ?></label>
336 <div class="inspector__control">
337 <input type="text" class="inspector__input" data-inspector-key="label" value="{{ data.label || '<?php echo esc_js( __( 'End time', 'booking' ) ); ?>' }}">
338 </div>
339 </div>
340
341 <div class="inspector__row">
342 <label class="inspector__label"><?php echo esc_html__( 'Name', 'booking' ); ?></label>
343 <div class="inspector__control">
344 <input type="text" class="inspector__input" value="{{ (data.name && data.name !== '' ? data.name : 'endtime') }}" disabled="disabled" aria-disabled="true">
345 <input type="hidden" class="inspector__input js-locked-name" data-inspector-key="name" data-locked="1" value="{{ (data.name && data.name !== '' ? data.name : 'endtime') }}">
346 <p class="wpbc_bfb__help" style="margin-top:6px;"><?php echo esc_html__( 'This field name is fixed for compatibility.', 'booking' ); ?></p>
347 </div>
348 </div>
349
350 <div class="inspector__row">
351 <div class="inspector__control ">
352 <span class="wpbc_ui__toggle">
353 <# var input_id = window.WPBC_BFB_Core.UI.WPBC_BFB_Toggle_Normalizer.generate_unique_id( 'wpbc_ins_auto_' + 'toggle_required' + '_' ); #>
354 <input type="checkbox" id="{{input_id}}" class="inspector__checkbox js-required-visible" checked disabled aria-disabled="true" data-wpbc-ui-no-toggle="1">
355 <label class="wpbc_ui__toggle_icon" for="{{input_id}}"></label>
356 <label class="wpbc_ui__toggle_label" for="{{input_id}}"><?php echo esc_html__( 'Required', 'booking' ); ?></label>
357 </span>
358 <input type="checkbox" class="inspector__checkbox js-required-proxy" data-inspector-key="required" data-locked="1" checked data-wpbc-ui-no-toggle="1" style="position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;">
359 <p class="wpbc_bfb__help" style="margin-inline-start:1em;display: inline-block;"><?php echo esc_html__( 'This field is always required.', 'booking' ); ?></p>
360 </div>
361 </div>
362
363 <div class="inspector__row">
364 <label class="inspector__label"><?php echo esc_html__( 'Help text', 'booking' ); ?></label>
365 <div class="inspector__control">
366 <textarea class="inspector__textarea" rows="3" data-inspector-key="help">{{ data.help || '' }}</textarea>
367 </div>
368 </div>
369 </div>
370 </section>
371
372 <section class="wpbc_bfb__inspector__group wpbc_ui__collapsible_group is-open" data-group="options">
373 <button type="button" class="group__header">
374 <h3><?php echo esc_html__( 'Time options', 'booking' ); ?></h3>
375 <i class="wpbc_ui_el__vert_menu_root_section_icon menu_icon icon-1x wpbc-bi-chevron-right"></i>
376 </button>
377
378 <div class="group__fields inspector__group__fields__times">
379 <?php /* ===== Generator — identical to Start Time; uses same class hooks ===== */ ?>
380 <div class="inspector__row">
381 <div class="inspector__control inspector__control__generator_times">
382
383 <# var __fmt_name = 'et_label_fmt_' + ( data.html_id ? data.html_id : ( 'id_' + String( Math.random() ).slice(2) ) ); #>
384 <h2><?php echo esc_html__( 'Generate times', 'booking' ); ?></h2>
385 <div class="wpbc_bfb__st_gen_format wpbc_inline_inputs" role="radiogroup" aria-label="<?php echo esc_attr__( 'Time format', 'booking' ); ?>">
386 <label class="inspector__label inspector__w_30"><?php echo esc_html__( 'Time format', 'booking' ); ?>:</label>
387 <div class="wpbc_inline_inputs inspector__w_70">
388
389 <input type="hidden" class="inspector__input js-st-label-fmt-value" data-inspector-key="gen_label_fmt" value="{{ data.gen_label_fmt || 'ampm' }}">
390
391 <label>
392 <input type="radio" name="{{ __fmt_name }}" class="js-st-label-fmt" value="ampm" <# if ( (data.gen_label_fmt||'ampm') === 'ampm' ) { #> checked <# } #> >
393 <?php echo esc_html__( 'AM/PM', 'booking' ); ?>
394 </label>
395 &nbsp;&nbsp;
396 <label>
397 <input type="radio" name="{{ __fmt_name }}" class="js-st-label-fmt" value="24h" <# if ( (data.gen_label_fmt||'ampm') === '24h' ) { #> checked <# } #> >
398 <?php echo esc_html__( '24H', 'booking' ); ?>
399 </label>
400 </div>
401 </div>
402
403 <div class="wpbc_bfb__st_gen_times" style="margin-top:8px;">
404 <!-- 24H group (masked text inputs) -->
405 <div class="js-st-24h wpbc_inline_inputs" <# if ( (data.gen_label_fmt||'24h') !== '24h' ) { #> style="display:none" hidden aria-hidden="true" <# } #>>
406 <label class="inspector__label inspector__w_30"><?php echo esc_html__( 'From / To', 'booking' ); ?>:</label>
407 <div class="wpbc_inline_inputs inspector__w_70">
408 <div class="inspector__control inspector__w_45">
409 <input type="text" class="inspector__input inspector__w_25 js-st-mask js-gen-start-24h" data-mask-kind="24h" placeholder="HH:MM" data-inspector-key="gen_start_24h" value="{{ data.gen_start_24h || '08:00' }}">
410 </div>
411 <div class="inspector__control inspector__w_10" style="text-align: center;font-size: 18px;line-height: 2;font-weight: 700;">&ndash;</div>
412 <div class="inspector__control inspector__w_45">
413 <input type="text" class="inspector__input inspector__w_25 js-st-mask js-gen-end-24h" data-mask-kind="24h" placeholder="HH:MM" data-inspector-key="gen_end_24h" value="{{ data.gen_end_24h || '22:00' }}">
414 </div>
415 </div>
416 </div>
417
418 <!-- AM/PM group (native time inputs) -->
419 <div class="js-st-ampm wpbc_inline_inputs" <# if ( (data.gen_label_fmt||'24h') === '24h' ) { #> style="display:none" hidden aria-hidden="true" <# } #>>
420 <label class="inspector__label inspector__w_30"><?php echo esc_html__( 'From / To', 'booking' ); ?>:</label>
421 <div class="wpbc_inline_inputs inspector__w_70">
422 <div class="inspector__control inspector__w_45">
423 <input type="time" class="inspector__input inspector__w_25 js-gen-start-ampm-time" step="300" data-inspector-key="gen_start_ampm_t" value="{{ data.gen_start_ampm_t || '08:00' }}">
424 </div>
425 <div class="inspector__control inspector__w_10" style="text-align: center;font-size: 18px;line-height: 2;font-weight: 700;">&ndash;</div>
426 <div class="inspector__control inspector__w_45">
427 <input type="time" class="inspector__input inspector__w_25 js-gen-end-ampm-time" step="300" data-inspector-key="gen_end_ampm_t" value="{{ data.gen_end_ampm_t || '22:00' }}">
428 </div>
429 </div>
430 </div>
431 </div>
432
433 <div class="wpbc_bfb__st_gen_step wpbc_inline_inputs">
434 <label class="inspector__label inspector__w_30"><?php echo esc_html__( 'Step', 'booking' ); ?></label>
435 <div class="wpbc_len_group wpbc_inline_inputs inspector__w_70" data-len-group="st-step-hours">
436 <div class="inspector__control inspector__w_10"><?php echo esc_html__( 'hours', 'booking' ); ?>:</div>
437 <input data-len-range type="range" class="inspector__input js-gen-step-h-range" min="0" max="12" step="1" value="{{ data.gen_step_h || 1 }}">
438 <input data-len-value type="number" class="inspector__input inspector__w_30 js-gen-step-h" data-inspector-key="gen_step_h" min="0" max="12" step="1" value="{{ data.gen_step_h || 1 }}">
439 </div>
440 </div>
441
442 <div class="wpbc_bfb__st_gen_step wpbc_inline_inputs">
443 <label class="inspector__label inspector__w_30"></label>
444 <div class="wpbc_len_group wpbc_inline_inputs inspector__w_70" data-len-group="st-step-minutes">
445 <div class="inspector__control inspector__w_10"><?php echo esc_html__( 'minutes', 'booking' ); ?>:</div>
446 <input data-len-range type="range" class="inspector__input js-gen-step-m-range" min="0" max="59" step="5" value="{{ data.gen_step_m || 0 }}">
447 <input data-len-value type="number" class="inspector__input inspector__w_30 js-gen-step-m" data-inspector-key="gen_step_m" min="0" max="59" step="5" value="{{ data.gen_step_m || 0 }}">
448 </div>
449 </div>
450
451 <div class="wpbc_bfb__options_toolbar wpbc_inline_inputs">
452 <div class="inspector__control inspector__w_100" style="text-align: center;">
453 <button type="button" class="button button-primary js-st-generate"><?php echo esc_html__( 'Generate times', 'booking' ); ?> <i class="menu_icon icon-1x wpbc_icn_arrow_downward" aria-hidden="true"></i></button>
454 </div>
455 </div>
456
457 </div>
458 </div>
459
460 <?php /* ===== Options editor ===== */ ?>
461 <div class="inspector__row wpbc_bfb__options_editor">
462 <div class="wpbc_bfb__options_list__header">
463 <div class="wpbc_bfb__header_col__drag-handle"></div>
464 <div class="wpbc_bfb__header_col__label"><?php echo esc_html__( 'Label', 'booking' ) . ' (' . esc_html__( 'any text', 'booking' ) . ')'; ?></div>
465 <div class="wpbc_bfb__header_col__value"><?php echo esc_html__( 'Time', 'booking' ); ?></div>
466 <div class="wpbc_bfb__header_col__action"></div>
467 </div>
468 <div class="wpbc_bfb__options_list">
469 <#
470 var _opts2 = Array.isArray( data.options ) ? data.options
471 : ( function(o){ var a=[],k; for ( k in (o || {}) ) { if ( Object.prototype.hasOwnProperty.call( o, k ) ) { a.push( o[ k ] ); } } return a; } )( data.options );
472 #>
473
474 <# _opts2.forEach( function( opt, idx ){
475 var _val = String( opt && opt.value || '' );
476 var __uid = 'wpbc_ins_et_' + Math.random().toString(36).slice(2,10);
477 var __sel = !!( opt && ( true === opt.selected || 'true' === opt.selected || 1 === opt.selected || '1' === opt.selected ) );
478 #>
479 <div class="wpbc_bfb__options_row" data-index="{{ idx }}">
480 <span class="wpbc_bfb__drag-handle" title="<?php echo esc_attr__( 'Drag to reorder', 'booking' ); ?>"><span class="wpbc_icn_drag_indicator"></span></span>
481
482 <input type="text" class="wpbc_bfb__opt-label" placeholder="<?php echo esc_attr__( 'Label (e.g. 05:00 PM)', 'booking' ); ?>" value="{{ opt && opt.label || '' }}">
483
484 <# if ( (data.gen_label_fmt||'24h') === '24h' ) { #>
485 <input type="text" class="wpbc_bfb__opt-time js-st-mask" data-mask-kind="24h" placeholder="HH:MM" value="{{ _val }}">
486 <# } else { #>
487 <input type="time" class="wpbc_bfb__opt-time js-st-time" step="300" value="{{ _val }}">
488 <# } #>
489
490 <input type="text" class="wpbc_bfb__opt-value" value="{{ _val }}" hidden>
491
492 <div class="wpbc_bfb__opt-selected">
493 <div class="inspector__control wpbc_ui__toggle">
494 <input type="checkbox" class="wpbc_bfb__opt-selected-chk inspector__input" id="{{ __uid }}" role="switch" aria-checked="{{ __sel ? 'true' : 'false' }}" <# if ( __sel ) { #> checked <# } #> >
495 <label class="wpbc_ui__toggle_icon_radio" for="{{ __uid }}"></label>
496 <label class="wpbc_ui__toggle_label" for="{{ __uid ?>"><?php echo esc_js( __( 'Default', 'booking' ) ); ?></label>
497 </div>
498 </div>
499
500 <div class="wpbc_ui_el wpbc_ui_el_container wpbc_ui_el__dropdown">
501 <a href="javascript:void(0)" data-toggle="wpbc_dropdown" aria-expanded="false" class="ul_dropdown_menu_toggle">
502 <i class="menu_icon icon-1x wpbc_icn_more_vert"></i>
503 </a>
504 <ul class="ul_dropdown_menu" role="menu" style="right:0px; left:auto;">
505 <li><a class="ul_dropdown_menu_li_action st_dropdown_action" data-st-action="add_after" href="javascript:void(0)"><?php echo esc_html__( 'Add New', 'booking' ); ?><i class="menu_icon icon-1x wpbc_icn_add_circle"></i></a></li>
506 <li><a class="ul_dropdown_menu_li_action st_dropdown_action" data-st-action="duplicate" href="javascript:void(0)"><?php echo esc_html__( 'Duplicate', 'booking' ); ?><i class="menu_icon icon-1x wpbc_icn_content_copy"></i></a></li>
507 <li class="divider"></li>
508 <li><a class="ul_dropdown_menu_li_action st_dropdown_action" data-st-action="remove" href="javascript:void(0)"><?php echo esc_html__( 'Remove', 'booking' ); ?><i class="menu_icon icon-1x wpbc_icn_delete_outline"></i></a></li>
509 </ul>
510 </div>
511 </div>
512 <# }); #>
513 </div>
514
515 <div class="wpbc_bfb__options_toolbar ">
516 <small class="desc"><?php echo esc_html__( 'Drag by handle to reorder. Only one “Default” can be checked.', 'booking' ); ?></small>
517 <div class="wpbc_bfb__options_toolbar wpbc_inline_inputs">
518 <div class="inspector__control inspector__w_15">
519 <button type="button" class="button js-st-clear"><?php echo esc_html__( 'Clear all', 'booking' ); ?></button>
520 </div>
521 <div class="inspector__control inspector__w_85">
522 <button type="button" class="button button-secondary js-st-add-option">
523 <i class="wpbc_ui_el__vert_nav_icon tooltip_right_offset menu_icon icon-1x wpbc_icn_add_circle" aria-hidden="true"></i>
524 <?php echo esc_html__( 'Add time', 'booking' ); ?>
525 </button>
526 </div>
527 </div>
528 </div>
529
530 <#
531 var __json = JSON.stringify(_opts2 || []);
532 __json = __json.replace(/<\/textarea/gi, '<\\/textarea');
533 #>
534 <textarea class="wpbc_bfb__options_state inspector__input" data-inspector-key="options" hidden>{{ __json }}</textarea>
535 </div>
536
537 <div class="inspector__row js-placeholder-row">
538 <label class="inspector__label"><?php echo esc_html__( 'Placeholder', 'booking' ); ?></label>
539 <div class="inspector__control">
540 <input type="text" class="inspector__input js-placeholder" data-inspector-key="placeholder" value="{{ data.placeholder || '<?php echo '--- ' . esc_js( __( 'Select time', 'booking' ) ) . ' ---'; ?>' }}">
541 <p class="wpbc_bfb__help js-placeholder-note" style="margin-top:6px;"><?php echo esc_html__( 'Placeholder is used when no default is set.', 'booking' ); ?></p>
542 </div>
543 </div>
544
545 </div>
546 </section>
547
548 <section class="wpbc_bfb__inspector__group wpbc_ui__collapsible_group" data-group="appearance">
549 <button type="button" class="group__header">
550 <h3><?php echo esc_html__( 'Appearance', 'booking' ); ?></h3>
551 <i class="wpbc_ui_el__vert_menu_root_section_icon menu_icon icon-1x wpbc-bi-chevron-right"></i>
552 </button>
553 <div class="group__fields">
554
555 <div class="inspector__row">
556 <label class="inspector__label"><?php echo esc_html__( 'CSS class', 'booking' ); ?></label>
557 <div class="inspector__control">
558 <input type="text" class="inspector__input" data-inspector-key="cssclass" value="{{ data.cssclass || '' }}">
559 </div>
560 </div>
561
562 <div class="inspector__row">
563 <label class="inspector__label"><?php echo esc_html__( 'HTML ID', 'booking' ); ?></label>
564 <div class="inspector__control">
565 <input type="text" class="inspector__input" data-inspector-key="html_id" value="{{ data.html_id || '' }}">
566 </div>
567 </div>
568
569 <div class="inspector__row">
570 <label class="inspector__label"><?php echo esc_html__( 'Min width', 'booking' ); ?></label>
571 <div class="inspector__control">
572 <input type="text" class="inspector__input" data-inspector-key="min_width" placeholder="180px" value="{{ data.min_width || '180px' }}">
573 </div>
574 </div>
575 </div>
576 </section>
577
578 </div><!-- .wpbc_bfb__inspector__body -->
579 </div><!-- .wpbc_bfb__inspector_endtime -->
580 </script>
581 <?php
582 }
583