| 1 |
// ================================================================================================= |
| 2 |
// == Pack: Static Text (WP-template-less; schema-driven) |
| 3 |
// == File: /includes/page-form-builder/field-packs/static-text/_out/static-text.js |
| 4 |
// == Depends: WPBC_BFB_Field_Base, Field_Renderer_Registry, Core.Sanitize, Exporter API |
| 5 |
// == Version: 1.0.1 (09.11.2025) — add base CSS class "wpbc_static_text" to preview & export |
| 6 |
// ================================================================================================= |
| 7 |
(function (w, d) { |
| 8 |
'use strict'; |
| 9 |
|
| 10 |
var Core = w.WPBC_BFB_Core || {}; |
| 11 |
var registry = Core.WPBC_BFB_Field_Renderer_Registry; |
| 12 |
var Base = Core.WPBC_BFB_Field_Base; |
| 13 |
|
| 14 |
if ( ! registry || typeof registry.register !== 'function' || ! Base ) { |
| 15 |
_wpbc?.dev?.error?.( 'wpbc_bfb_field_static_text', 'Core registry/base missing' ); |
| 16 |
return; |
| 17 |
} |
| 18 |
|
| 19 |
/** |
| 20 |
* Field Renderer: static_text |
| 21 |
* - Renders a single text element with configurable tag, align, bold, italic. |
| 22 |
* - Supports pass-through HTML (preview only) if html_allowed=1; otherwise escapes + optional nl2br. |
| 23 |
* |
| 24 |
* @class wpbc_bfb_field_static_text |
| 25 |
* @extends Core.WPBC_BFB_Field_Base |
| 26 |
*/ |
| 27 |
class wpbc_bfb_field_static_text extends Base { |
| 28 |
|
| 29 |
/** |
| 30 |
* Defaults (must mirror PHP schema). |
| 31 |
* @returns {{type:string,text:string,tag:string,align:string,bold:number,italic:number,html_allowed:number,nl2br:number,cssclass_extra:string,name:string,html_id:string,help:string,usage_key:string}} |
| 32 |
*/ |
| 33 |
static get_defaults() { |
| 34 |
return { |
| 35 |
type : 'static_text', |
| 36 |
text : 'Add your message here…', |
| 37 |
tag : 'p', |
| 38 |
align : 'left', |
| 39 |
bold : 0, |
| 40 |
italic : 0, |
| 41 |
html_allowed : 0, |
| 42 |
nl2br : 1, |
| 43 |
cssclass_extra : '', |
| 44 |
name : '', |
| 45 |
html_id : '', |
| 46 |
help : '', |
| 47 |
usage_key : 'static_text' |
| 48 |
}; |
| 49 |
} |
| 50 |
|
| 51 |
/** |
| 52 |
* Whitelist tag. |
| 53 |
* @param {string} v |
| 54 |
* @returns {string} |
| 55 |
*/ |
| 56 |
static allow_tag( v ) { |
| 57 |
var t = String( v || 'p' ).toLowerCase(); |
| 58 |
var ok = { p:1,label:1,span:1,small:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1 }; |
| 59 |
return ok[t] ? t : 'p'; |
| 60 |
} |
| 61 |
|
| 62 |
/** |
| 63 |
* Whitelist align. |
| 64 |
* @param {string} v |
| 65 |
* @returns {string} |
| 66 |
*/ |
| 67 |
static allow_align( v ) { |
| 68 |
var a = String( v || 'left' ).toLowerCase(); |
| 69 |
var ok = { left:1, center:1, right:1 }; |
| 70 |
return ok[a] ? a : 'left'; |
| 71 |
} |
| 72 |
|
| 73 |
/** |
| 74 |
* Escape + optional nl2br for preview/export when HTML is not allowed. |
| 75 |
* @param {string} raw |
| 76 |
* @param {boolean} do_nl2br |
| 77 |
* @returns {string} |
| 78 |
*/ |
| 79 |
static escape_text( raw, do_nl2br ) { |
| 80 |
var esc = Core.WPBC_BFB_Sanitize.escape_html( String( raw || '' ) ); |
| 81 |
if ( do_nl2br && ! /<br\s*\/?>/i.test( esc ) ) { |
| 82 |
esc = esc.replace(/\n/g, '<br>'); |
| 83 |
} |
| 84 |
return esc; |
| 85 |
} |
| 86 |
|
| 87 |
/** |
| 88 |
* Main render entry (called by Builder). |
| 89 |
* Adds the base class "wpbc_static_text" to the text element for styling parity with export. |
| 90 |
* |
| 91 |
* @param {HTMLElement} el |
| 92 |
* @param {Object} data |
| 93 |
* @param {{builder?:any}} ctx |
| 94 |
* @returns {void} |
| 95 |
*/ |
| 96 |
static render( el, data, ctx ) { |
| 97 |
if ( ! el ) { return; } |
| 98 |
|
| 99 |
var sanit = Core.WPBC_BFB_Sanitize || {}; |
| 100 |
var esc_html = sanit.escape_html || (v => String(v).replace(/[<>&"]/g, '')); |
| 101 |
var sanitize_id = sanit.sanitize_html_id || (v => String(v).trim()); |
| 102 |
var sanitize_name = sanit.sanitize_html_name || (v => String(v).trim()); |
| 103 |
var sanitize_cls = sanit.sanitize_css_classlist || (v => String(v).trim()); |
| 104 |
|
| 105 |
var d_norm = Object.assign( {}, this.get_defaults(), data || {} ); |
| 106 |
var tag = this.allow_tag( d_norm.tag ); |
| 107 |
var align = this.allow_align( d_norm.align ); |
| 108 |
|
| 109 |
var html_id = d_norm.html_id ? sanitize_id( String( d_norm.html_id ) ) : ''; |
| 110 |
var name_val = d_norm.name ? sanitize_name( String( d_norm.name ) ) : ''; |
| 111 |
var cls_extra_raw = String( d_norm.cssclass_extra || '' ); |
| 112 |
var cls_extra = sanitize_cls( cls_extra_raw ); |
| 113 |
|
| 114 |
// Persist sanitized dataset (helps Inspector & snapshots) |
| 115 |
if ( el.dataset.html_id !== html_id ) { el.dataset.html_id = html_id; } |
| 116 |
if ( el.dataset.name !== name_val ) { el.dataset.name = name_val; } |
| 117 |
if ( el.dataset.cssclass_extra !== cls_extra ) { el.dataset.cssclass_extra = cls_extra; } |
| 118 |
if ( el.dataset.tag !== tag ) { el.dataset.tag = tag; } |
| 119 |
if ( el.dataset.align !== align ) { el.dataset.align = align; } |
| 120 |
|
| 121 |
var id_attr = html_id ? ' id="' + esc_html( html_id ) + '"' : ''; |
| 122 |
var name_attr = name_val ? ' name="' + esc_html( name_val ) + '"' : ''; |
| 123 |
|
| 124 |
// --- NEW: base class on the TEXT element --- |
| 125 |
var base_cls = 'wpbc_static_text'; |
| 126 |
var tag_cls_full = base_cls + ( cls_extra ? ( ' ' + cls_extra ) : '' ); |
| 127 |
var cls_attr = ' class="' + esc_html( tag_cls_full ) + '"'; |
| 128 |
|
| 129 |
var style_bits = []; |
| 130 |
if ( align ) { style_bits.push( 'text-align:' + align ); } |
| 131 |
if ( d_norm.bold ) { style_bits.push( 'font-weight:bold' ); } |
| 132 |
if ( d_norm.italic ) { style_bits.push( 'font-style:italic' ); } |
| 133 |
var style_attr = style_bits.length ? ( ' style="' + style_bits.join(';') + '"' ) : ''; |
| 134 |
|
| 135 |
// Content |
| 136 |
var content = ''; |
| 137 |
if ( d_norm.html_allowed ) { |
| 138 |
content = String( d_norm.text || '' ); |
| 139 |
} else { |
| 140 |
content = this.escape_text( d_norm.text, !! d_norm.nl2br ); |
| 141 |
} |
| 142 |
|
| 143 |
var help_html = d_norm.help ? '<div class="wpbc_bfb__help">' + esc_html( String( d_norm.help ) ) + '</div>' : ''; |
| 144 |
|
| 145 |
el.innerHTML = |
| 146 |
'<span class="wpbc_bfb__no-drag-zone" inert="">' + |
| 147 |
'<' + tag + id_attr + name_attr + cls_attr + style_attr + '>' + content + '</' + tag + '>' + |
| 148 |
help_html + |
| 149 |
'</span>'; |
| 150 |
|
| 151 |
Core.UI?.WPBC_BFB_Overlay?.ensure?.( ctx?.builder, el ); |
| 152 |
} |
| 153 |
|
| 154 |
/** |
| 155 |
* Optional hook after drop (keep base behavior). |
| 156 |
* @param {Object} data |
| 157 |
* @param {HTMLElement} el |
| 158 |
* @param {{palette_item?:HTMLElement}} ctx |
| 159 |
* @returns {void} |
| 160 |
*/ |
| 161 |
static on_field_drop( data, el, ctx ) { |
| 162 |
try { super.on_field_drop?.( data, el, ctx ); } catch (e) {} |
| 163 |
} |
| 164 |
} |
| 165 |
|
| 166 |
// Register renderer |
| 167 |
try { |
| 168 |
registry.register( 'static_text', wpbc_bfb_field_static_text ); |
| 169 |
} catch (e) { |
| 170 |
_wpbc?.dev?.error?.( 'wpbc_bfb_field_static_text.register', e ); |
| 171 |
} |
| 172 |
|
| 173 |
|
| 174 |
// ----------------------------------------------------------------------------------------------------------------- |
| 175 |
// Export for "Booking Form" (Advanced Form shortcode) |
| 176 |
// ----------------------------------------------------------------------------------------------------------------- |
| 177 |
/** |
| 178 |
* Register Booking Form exporter callback (Advanced Form) for "static_text". |
| 179 |
* |
| 180 |
* This exporter: |
| 181 |
* - Emits plain HTML using the same tag/align/bold/italic rules as the Builder preview. |
| 182 |
* - Adds the base class "wpbc_static_text" plus any extra CSS classes. |
| 183 |
* - Respects: |
| 184 |
* • html_allowed = 1 → pass-through HTML (no escaping). |
| 185 |
* • html_allowed = 0 → escape + optional nl2br (via wpbc_bfb_field_static_text.escape_text()). |
| 186 |
* • html_id / name → rendered as id="…" / name="…". |
| 187 |
* - Help text is appended centrally by WPBC_BFB_Exporter.render_field_node(), same as other packs. |
| 188 |
*/ |
| 189 |
function register_static_text_booking_form_exporter() { |
| 190 |
|
| 191 |
var Exp = w.WPBC_BFB_Exporter; |
| 192 |
if ( ! Exp || typeof Exp.register !== 'function' ) { return; } |
| 193 |
if ( typeof Exp.has_exporter === 'function' && Exp.has_exporter( 'static_text' ) ) { return; } |
| 194 |
|
| 195 |
var S = Core.WPBC_BFB_Sanitize || {}; |
| 196 |
var esc_html = S.escape_html || function( v ){ return String( v ); }; |
| 197 |
var sanitizeId = S.sanitize_html_id || function( v ){ return String( v ).trim(); }; |
| 198 |
var sanitizeNm = S.sanitize_html_name || function( v ){ return String( v ).trim(); }; |
| 199 |
var sanitizeCl = S.sanitize_css_classlist|| function( v ){ return String( v ).trim(); }; |
| 200 |
|
| 201 |
/** |
| 202 |
* @type {WPBC_BFB_ExporterCallback} |
| 203 |
* @param {Object} field |
| 204 |
* @param {function(string):void} emit |
| 205 |
* @param {Object} [extras] |
| 206 |
*/ |
| 207 |
var exporter_callback = function( field, emit, extras ) { |
| 208 |
extras = extras || {}; |
| 209 |
|
| 210 |
// Merge with defaults so all props are present (mirrors preview). |
| 211 |
var defs = wpbc_bfb_field_static_text.get_defaults(); |
| 212 |
var d = Object.assign( {}, defs, field || {} ); |
| 213 |
|
| 214 |
var tag = wpbc_bfb_field_static_text.allow_tag( d.tag ); |
| 215 |
var align = wpbc_bfb_field_static_text.allow_align( d.align ); |
| 216 |
|
| 217 |
var html_id = d.html_id ? sanitizeId( String( d.html_id ) ) : ''; |
| 218 |
var name_val = d.name ? sanitizeNm( String( d.name ) ) : ''; |
| 219 |
|
| 220 |
// Extra CSS classes from Inspector / schema. |
| 221 |
var cls_extra_raw = String( d.cssclass_extra || d.cssclass || d.class || '' ); |
| 222 |
var cls_extra = sanitizeCl( cls_extra_raw ); |
| 223 |
|
| 224 |
// Base class for styling parity between Builder preview and exported form. |
| 225 |
var base_cls = 'wpbc_static_text'; |
| 226 |
var cls_full = base_cls + ( cls_extra ? ( ' ' + cls_extra ) : '' ); |
| 227 |
|
| 228 |
var id_attr = html_id ? ' id="' + esc_html( html_id ) + '"' : ''; |
| 229 |
var name_attr = name_val ? ' name="' + esc_html( name_val ) + '"' : ''; |
| 230 |
var cls_attr = ' class="' + esc_html( cls_full ) + '"'; |
| 231 |
|
| 232 |
// Inline styles: text-align + bold/italic flags. |
| 233 |
var style_bits = []; |
| 234 |
if ( align ) { style_bits.push( 'text-align:' + align ); } |
| 235 |
if ( d.bold ) { style_bits.push( 'font-weight:bold' ); } |
| 236 |
if ( d.italic ) { style_bits.push( 'font-style:italic' ); } |
| 237 |
var style_attr = style_bits.length |
| 238 |
? ' style="' + esc_html( style_bits.join( ';' ) ) + '"' |
| 239 |
: ''; |
| 240 |
|
| 241 |
// Content: escape + nl2br when HTML is NOT allowed; raw when allowed. |
| 242 |
var content; |
| 243 |
if ( d.html_allowed ) { |
| 244 |
content = String( d.text || '' ); |
| 245 |
} else { |
| 246 |
content = wpbc_bfb_field_static_text.escape_text( d.text, !! d.nl2br ); |
| 247 |
} |
| 248 |
|
| 249 |
emit( |
| 250 |
'<' + tag + id_attr + name_attr + cls_attr + style_attr + '>' + |
| 251 |
content + |
| 252 |
'</' + tag + '>' |
| 253 |
); |
| 254 |
// NOTE: |
| 255 |
// - Help text (field.help) is output by WPBC_BFB_Exporter.render_field_node() |
| 256 |
// beneath this block, keeping behavior consistent with other field packs. |
| 257 |
}; |
| 258 |
|
| 259 |
Exp.register( 'static_text', exporter_callback ); |
| 260 |
} |
| 261 |
|
| 262 |
// Try immediate registration; if core isn’t ready yet, wait for the event. |
| 263 |
if ( w.WPBC_BFB_Exporter && typeof w.WPBC_BFB_Exporter.register === 'function' ) { |
| 264 |
register_static_text_booking_form_exporter(); |
| 265 |
} else { |
| 266 |
d.addEventListener( |
| 267 |
'wpbc:bfb:exporter-ready', |
| 268 |
register_static_text_booking_form_exporter, |
| 269 |
{ once: true } |
| 270 |
); |
| 271 |
} |
| 272 |
|
| 273 |
|
| 274 |
// ----------------------------------------------------------------------------------------------------------------- |
| 275 |
// Export for "Booking Data" (Content of booking fields data) |
| 276 |
// ----------------------------------------------------------------------------------------------------------------- |
| 277 |
/** |
| 278 |
* Register Booking Data exporter callback ("Content of booking fields data") for "static_text". |
| 279 |
* |
| 280 |
* Static Text is purely presentational and does not carry user-entered values, |
| 281 |
* so it is intentionally omitted from the "Content of booking fields data" output. |
| 282 |
* This exporter therefore does nothing (emits no line). |
| 283 |
*/ |
| 284 |
function register_static_text_booking_data_exporter() { |
| 285 |
|
| 286 |
var C = w.WPBC_BFB_ContentExporter; |
| 287 |
if ( ! C || typeof C.register !== 'function' ) { return; } |
| 288 |
if ( typeof C.has_exporter === 'function' && C.has_exporter( 'static_text' ) ) { return; } |
| 289 |
|
| 290 |
var exporter_callback = function( field, emit, extras ) { |
| 291 |
// Intentionally empty: static_text has no dynamic token/value to show in booking data. |
| 292 |
return; |
| 293 |
}; |
| 294 |
|
| 295 |
C.register( 'static_text', exporter_callback ); |
| 296 |
} |
| 297 |
|
| 298 |
if ( w.WPBC_BFB_ContentExporter && typeof w.WPBC_BFB_ContentExporter.register === 'function' ) { |
| 299 |
register_static_text_booking_data_exporter(); |
| 300 |
} else { |
| 301 |
d.addEventListener( |
| 302 |
'wpbc:bfb:content-exporter-ready', |
| 303 |
register_static_text_booking_data_exporter, |
| 304 |
{ once: true } |
| 305 |
); |
| 306 |
} |
| 307 |
|
| 308 |
})( window, document ); |
| 309 |
|