| 1 |
// File: /includes/page-form-builder/field-packs/wizard-nav/_out/wizard-nav.js |
| 2 |
(function ( w ) { |
| 3 |
'use strict'; |
| 4 |
|
| 5 |
var Core = w.WPBC_BFB_Core || {}; |
| 6 |
var registry = Core.WPBC_BFB_Field_Renderer_Registry; |
| 7 |
var Base = Core.WPBC_BFB_Field_Base; |
| 8 |
|
| 9 |
if ( ! registry || typeof registry.register !== 'function' || ! Base ) { |
| 10 |
_wpbc?.dev?.error?.( 'WPBC_BFB_Field_Wizard_Nav', 'Core registry/base missing' ); |
| 11 |
return; |
| 12 |
} |
| 13 |
|
| 14 |
/** |
| 15 |
* WPBC BFB: Field Renderer for "wizard_nav" (Schema-driven) |
| 16 |
* - Inspector is rendered by Factory (from PHP schema). |
| 17 |
* - No wp.template usage for preview. |
| 18 |
* - Must output: |
| 19 |
* <a class="wpbc_button_light wpbc_wizard_step_button wpbc_wizard_step_{N} [cssclass_extra]">Label</a> |
| 20 |
*/ |
| 21 |
class WPBC_BFB_Field_Wizard_Nav extends Base { |
| 22 |
|
| 23 |
/** |
| 24 |
* Return default props for "wizard_nav" field. |
| 25 |
* Must stay in sync with PHP schema defaults. |
| 26 |
* |
| 27 |
* @returns {Object} |
| 28 |
*/ |
| 29 |
static get_defaults() { |
| 30 |
return { |
| 31 |
type : 'wizard_nav', |
| 32 |
direction : 'next', // 'next' | 'back' |
| 33 |
label : 'Next', |
| 34 |
target_step : 2, // >= 1 |
| 35 |
cssclass_extra : '', |
| 36 |
name : '', |
| 37 |
html_id : '', |
| 38 |
help : '', |
| 39 |
usage_key : 'wizard_nav' |
| 40 |
}; |
| 41 |
} |
| 42 |
|
| 43 |
/** |
| 44 |
* Render the preview markup into the field element. |
| 45 |
* |
| 46 |
* @param {HTMLElement} el Field root element inside the canvas. |
| 47 |
* @param {Object} data Field props (already normalized by schema). |
| 48 |
* @param {Object} ctx Context: { builder, sanit, ... } |
| 49 |
* @returns {void} |
| 50 |
*/ |
| 51 |
static render( el, data, ctx ) { |
| 52 |
|
| 53 |
if ( ! el ) { |
| 54 |
return; |
| 55 |
} |
| 56 |
|
| 57 |
// Normalize against defaults first. |
| 58 |
const d = this.normalize_data( data ); |
| 59 |
|
| 60 |
// ----- Core sanitize helpers (static) ----- |
| 61 |
const eh = ( v ) => Core.WPBC_BFB_Sanitize.escape_html( v ); |
| 62 |
const sid = ( v ) => Core.WPBC_BFB_Sanitize.sanitize_html_id( v ); |
| 63 |
const sname = ( v ) => Core.WPBC_BFB_Sanitize.sanitize_html_name( v ); |
| 64 |
const sclass = ( v ) => Core.WPBC_BFB_Sanitize.sanitize_css_classlist( v ); |
| 65 |
const to_int = ( v, def ) => { |
| 66 |
const n = parseInt( v, 10 ); |
| 67 |
return ( isNaN( n ) || n < 1 ) ? def : n; |
| 68 |
}; |
| 69 |
|
| 70 |
// Direction & label coherence. |
| 71 |
const dir = ( d.direction === 'back' ) ? 'back' : 'next'; |
| 72 |
const step_def = ( dir === 'next' ) ? 2 : 1; |
| 73 |
const step_num = to_int( d.target_step, step_def ); |
| 74 |
const label_txt = ( typeof d.label === 'string' && d.label.length ) ? d.label : ( dir === 'next' ? 'Next' : 'Back' ); |
| 75 |
|
| 76 |
// Public attributes. |
| 77 |
const html_id = d.html_id ? sid( String( d.html_id ) ) : ''; |
| 78 |
const name_val = d.name ? sname( String( d.name ) ) : ''; |
| 79 |
const cls_extra = sclass( String( d.cssclass_extra || '' ) ); |
| 80 |
|
| 81 |
// Persist useful props on dataset (do not mutate wrapper classes directly). |
| 82 |
if ( 'cssclass_extra' in d && el.dataset.cssclass_extra !== cls_extra ) { |
| 83 |
el.dataset.cssclass_extra = cls_extra; |
| 84 |
} |
| 85 |
if ( 'html_id' in d && el.dataset.html_id !== html_id ) { |
| 86 |
el.dataset.html_id = html_id; |
| 87 |
} |
| 88 |
if ( 'name' in d && el.dataset.name !== name_val ) { |
| 89 |
el.dataset.name = name_val; |
| 90 |
} |
| 91 |
if ( 'target_step' in d && String( el.dataset.target_step ) !== String( step_num ) ) { |
| 92 |
el.dataset.target_step = String( step_num ); |
| 93 |
} |
| 94 |
if ( 'direction' in d && el.dataset.direction !== dir ) { |
| 95 |
el.dataset.direction = dir; |
| 96 |
} |
| 97 |
|
| 98 |
// Attribute fragments. |
| 99 |
const id_attr = html_id ? ` id="${eh( html_id )}"` : ''; |
| 100 |
const name_attr = name_val ? ` name="${eh( name_val )}"` : ''; |
| 101 |
const req_cls = `wpbc_button_light wpbc_wizard_step_button wpbc_wizard_step_${String( step_num )}`; |
| 102 |
const cls_attr = ` class="${req_cls}${cls_extra ? ' ' + eh( cls_extra ) : ''}"`; |
| 103 |
const href_attr = ` href="javascript:void(0);"`; |
| 104 |
|
| 105 |
// Optional help text below the button. |
| 106 |
const help_html = d.help ? `<div class="wpbc_bfb__help">${eh( d.help )}</div>` : ''; |
| 107 |
|
| 108 |
// Render preview HTML. |
| 109 |
el.innerHTML = ` |
| 110 |
<span class="wpbc_bfb__noaction wpbc_bfb__no-drag-zone" inert=""> |
| 111 |
<div class="wpbc_bfb__field-preview"> |
| 112 |
<a${href_attr}${cls_attr}${id_attr}${name_attr}>${eh( label_txt )}</a> |
| 113 |
</div> |
| 114 |
${help_html} |
| 115 |
</span> |
| 116 |
`; |
| 117 |
|
| 118 |
// Overlay (handles/toolbars). |
| 119 |
Core.UI?.WPBC_BFB_Overlay?.ensure?.( ctx?.builder, el ); |
| 120 |
} |
| 121 |
|
| 122 |
/** |
| 123 |
* Optional hook executed after field is dropped from the palette. |
| 124 |
* |
| 125 |
* @param {Object} data |
| 126 |
* @param {HTMLElement} el |
| 127 |
* @param {Object} ctx |
| 128 |
* @returns {void} |
| 129 |
*/ |
| 130 |
static on_field_drop( data, el, ctx ) { |
| 131 |
// Keep base behavior (auto-name from label, etc.). |
| 132 |
super.on_field_drop?.( data, el, ctx ); |
| 133 |
} |
| 134 |
} |
| 135 |
|
| 136 |
try { |
| 137 |
registry.register( 'wizard_nav', WPBC_BFB_Field_Wizard_Nav ); |
| 138 |
} catch ( e ) { _wpbc?.dev?.error?.( 'WPBC_BFB_Field_Wizard_Nav.register', e ); } |
| 139 |
|
| 140 |
|
| 141 |
// ----------------------------------------------------------------------------------------------------------------- |
| 142 |
// Export for "Booking Form" (Advanced Form shortcode) |
| 143 |
// ----------------------------------------------------------------------------------------------------------------- |
| 144 |
/** |
| 145 |
* Booking Form exporter callback for "wizard_nav". |
| 146 |
* |
| 147 |
* Produces anchors equivalent to the legacy exporter: |
| 148 |
* <a class="wpbc_button_light wpbc_wizard_step_button wpbc_wizard_step_2 extra">Next</a> |
| 149 |
* |
| 150 |
* Notes: |
| 151 |
* - No shortcode; this is pure HTML (navigation control, not a data field). |
| 152 |
* - Help text is appended centrally by WPBC_BFB_Exporter.render_field_node(). |
| 153 |
*/ |
| 154 |
function register_wizard_nav_booking_form_exporter() { |
| 155 |
|
| 156 |
var Exp = w.WPBC_BFB_Exporter; |
| 157 |
if ( ! Exp || typeof Exp.register !== 'function' ) { return; } |
| 158 |
if ( typeof Exp.has_exporter === 'function' && Exp.has_exporter( 'wizard_nav' ) ) { return; } |
| 159 |
|
| 160 |
var S = Core.WPBC_BFB_Sanitize || {}; |
| 161 |
var esc_html = S.escape_html || function( v ){ return String( v ); }; |
| 162 |
var sid = S.sanitize_html_id || function( v ){ return String( v ).trim(); }; |
| 163 |
var scls = S.sanitize_css_classlist || function( v ){ return String( v ).trim(); }; |
| 164 |
|
| 165 |
/** |
| 166 |
* @type {WPBC_BFB_ExporterCallback} |
| 167 |
*/ |
| 168 |
Exp.register( 'wizard_nav', function( field, emit, extras ) { |
| 169 |
extras = extras || {}; |
| 170 |
|
| 171 |
var ctx = extras.ctx || {}; |
| 172 |
var usedIds = ( ctx.usedIds instanceof Set ) ? ctx.usedIds : null; |
| 173 |
|
| 174 |
// Merge with defaults to keep behavior stable even if some props are missing. |
| 175 |
var defs = ( typeof WPBC_BFB_Field_Wizard_Nav.get_defaults === 'function' ) |
| 176 |
? WPBC_BFB_Field_Wizard_Nav.get_defaults() |
| 177 |
: {}; |
| 178 |
var d = Object.assign( {}, defs, field || {} ); |
| 179 |
|
| 180 |
// Direction & label logic (same as preview). |
| 181 |
var dir = ( d.direction === 'back' ) ? 'back' : 'next'; |
| 182 |
var step_raw = parseInt( d.target_step, 10 ); |
| 183 |
var step_num = ( Number.isFinite( step_raw ) && step_raw > 0 ) |
| 184 |
? step_raw |
| 185 |
: ( dir === 'back' ? 1 : 2 ); |
| 186 |
|
| 187 |
var label_txt = ( typeof d.label === 'string' && d.label.trim().length ) |
| 188 |
? d.label.trim() |
| 189 |
: ( dir === 'back' ? 'Back' : 'Next' ); |
| 190 |
|
| 191 |
// HTML ID: sanitize + ensure uniqueness across the export. |
| 192 |
var html_id = d.html_id ? sid( String( d.html_id ) ) : ''; |
| 193 |
if ( html_id && usedIds ) { |
| 194 |
var base = html_id; |
| 195 |
var candidate = base; |
| 196 |
var i = 2; |
| 197 |
while ( usedIds.has( candidate ) ) { |
| 198 |
candidate = base + '_' + ( i++ ); |
| 199 |
} |
| 200 |
usedIds.add( candidate ); |
| 201 |
html_id = candidate; |
| 202 |
} |
| 203 |
|
| 204 |
// Extra classes (in addition to required base wizard nav classes). |
| 205 |
var extra_raw = String( d.cssclass_extra || d.cssclass || d.class || '' ); |
| 206 |
var extra_cls = scls( extra_raw ); |
| 207 |
|
| 208 |
var req_cls = 'wpbc_button_light wpbc_wizard_step_button wpbc_wizard_step_' + String( step_num ); |
| 209 |
var full_cls = req_cls + ( extra_cls ? ( ' ' + esc_html( extra_cls ) ) : '' ); |
| 210 |
|
| 211 |
var id_attr = html_id ? ( ' id="' + esc_html( html_id ) + '"' ) : ''; |
| 212 |
|
| 213 |
// Final anchor — no href (click is handled externally). |
| 214 |
emit( |
| 215 |
'<a class="' + full_cls + '"' + id_attr + '>' + |
| 216 |
esc_html( label_txt ) + |
| 217 |
'</a>' |
| 218 |
); |
| 219 |
|
| 220 |
// NOTE: |
| 221 |
// - Help text (field.help) is output by WPBC_BFB_Exporter.render_field_node() |
| 222 |
// beneath this block, same as for other packs. |
| 223 |
} ); |
| 224 |
} |
| 225 |
|
| 226 |
if ( w.WPBC_BFB_Exporter && typeof w.WPBC_BFB_Exporter.register === 'function' ) { |
| 227 |
register_wizard_nav_booking_form_exporter(); |
| 228 |
} else if ( typeof document !== 'undefined' ) { |
| 229 |
document.addEventListener( |
| 230 |
'wpbc:bfb:exporter-ready', |
| 231 |
register_wizard_nav_booking_form_exporter, |
| 232 |
{ once: true } |
| 233 |
); |
| 234 |
} |
| 235 |
|
| 236 |
|
| 237 |
// ----------------------------------------------------------------------------------------------------------------- |
| 238 |
// Export for "Booking Data" (Content of booking fields data) |
| 239 |
// ----------------------------------------------------------------------------------------------------------------- |
| 240 |
/** |
| 241 |
* Booking Data exporter callback for "wizard_nav". |
| 242 |
* |
| 243 |
* Wizard navigation buttons do not carry user-entered values, |
| 244 |
* so they are intentionally omitted from the "Content of booking fields data". |
| 245 |
*/ |
| 246 |
function register_wizard_nav_booking_data_exporter() { |
| 247 |
|
| 248 |
var C = w.WPBC_BFB_ContentExporter; |
| 249 |
if ( ! C || typeof C.register !== 'function' ) { return; } |
| 250 |
if ( typeof C.has_exporter === 'function' && C.has_exporter( 'wizard_nav' ) ) { return; } |
| 251 |
|
| 252 |
C.register( 'wizard_nav', function( field, emit, extras ) { |
| 253 |
// Intentionally no output: nav buttons are not part of data template. |
| 254 |
return; |
| 255 |
} ); |
| 256 |
} |
| 257 |
|
| 258 |
if ( w.WPBC_BFB_ContentExporter && typeof w.WPBC_BFB_ContentExporter.register === 'function' ) { |
| 259 |
register_wizard_nav_booking_data_exporter(); |
| 260 |
} else if ( typeof document !== 'undefined' ) { |
| 261 |
document.addEventListener( |
| 262 |
'wpbc:bfb:content-exporter-ready', |
| 263 |
register_wizard_nav_booking_data_exporter, |
| 264 |
{ once: true } |
| 265 |
); |
| 266 |
} |
| 267 |
|
| 268 |
})( window ); |
| 269 |
|