PluginProbe
Booking Calendar / 11.8
Booking Calendar v11.8
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-duration / field-durationtime-wptpl.php

field-durationtime-wptpl.php in Booking Calendar 11.8, at includes/page-form-builder/field-packs/time-duration/field-durationtime-wptpl.php

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