| 1 |
(function () { |
| 2 |
'use strict'; |
| 3 |
|
| 4 |
var _typoKeys = { |
| 5 |
family:'font-family', weight:'font-weight', style:'font-style', |
| 6 |
transform:'text-transform', decoration:'text-decoration', |
| 7 |
sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m', |
| 8 |
lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m', |
| 9 |
letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m', |
| 10 |
wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m' |
| 11 |
}; |
| 12 |
var _typoUnits = { size:'sizeUnit', lineHeight:'lineHeightUnit', letterSpacing:'letterSpacingUnit', wordSpacing:'wordSpacingUnit' }; |
| 13 |
var _typoUnitDefaults = { size:'px', lineHeight:'', letterSpacing:'px', wordSpacing:'px' }; |
| 14 |
function typoCssVarsForEl(el, obj, prefix) { |
| 15 |
if (!obj || typeof obj !== 'object') return; |
| 16 |
Object.keys(_typoKeys).forEach(function (k) { |
| 17 |
var v = obj[k]; if (v === undefined || v === '') return; |
| 18 |
var prop = _typoKeys[k]; |
| 19 |
var base = k.replace(/Desktop|Tablet|Mobile/, ''); |
| 20 |
var uKey = _typoUnits[base]; |
| 21 |
if (uKey && typeof v === 'number') v = v + (obj[uKey] || _typoUnitDefaults[base] || ''); |
| 22 |
el.style.setProperty(prefix + prop, v); |
| 23 |
}); |
| 24 |
} |
| 25 |
|
| 26 |
function makeEl(tag, className, styles) { |
| 27 |
var el = document.createElement(tag); |
| 28 |
if (className) el.className = className; |
| 29 |
if (styles) Object.keys(styles).forEach(function (k) { el.style[k] = styles[k]; }); |
| 30 |
return el; |
| 31 |
} |
| 32 |
|
| 33 |
function makeText(tag, className, text, styles) { |
| 34 |
var el = makeEl(tag, className, styles); |
| 35 |
el.textContent = text; |
| 36 |
return el; |
| 37 |
} |
| 38 |
|
| 39 |
function init() { |
| 40 |
document.querySelectorAll('.bkbg-oh-app').forEach(function (appEl) { |
| 41 |
if (appEl.dataset.rendered) return; |
| 42 |
appEl.dataset.rendered = '1'; |
| 43 |
|
| 44 |
var opts; |
| 45 |
try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; } |
| 46 |
var o = Object.assign({ |
| 47 |
headline: 'Still have questions?', |
| 48 |
subheadline: '', |
| 49 |
showHeadline: true, |
| 50 |
objections: [], |
| 51 |
layout: 'stack', |
| 52 |
style: 'split', |
| 53 |
showIcon: true, |
| 54 |
objectionLabel: 'Concern', |
| 55 |
responseLabel: 'Our Answer', |
| 56 |
borderRadius: 12, |
| 57 |
gap: 16, |
| 58 |
bgColor: '#ffffff', |
| 59 |
headlineColor: '#0f172a', |
| 60 |
subColor: '#64748b', |
| 61 |
objectionBg: '#fff7ed', |
| 62 |
objectionColor: '#9a3412', |
| 63 |
objectionBorderColor: '#fed7aa', |
| 64 |
responseBg: '#f0fdf4', |
| 65 |
responseColor: '#166534', |
| 66 |
responseBorderColor: '#bbf7d0', |
| 67 |
labelColor: '#64748b', |
| 68 |
iconBg: '#f1f5f9' |
| 69 |
}, opts); |
| 70 |
|
| 71 |
var block = makeEl('div', 'bkbg-oh-block', { background: o.bgColor }); |
| 72 |
typoCssVarsForEl(block, o.headlineTypo, '--bkbg-oh-hl-'); |
| 73 |
typoCssVarsForEl(block, o.bodyTypo, '--bkbg-oh-bd-'); |
| 74 |
|
| 75 |
// Headline |
| 76 |
if (o.showHeadline) { |
| 77 |
if (o.headline) block.appendChild(makeText('h2', 'bkbg-oh-headline', o.headline, { color: o.headlineColor })); |
| 78 |
if (o.subheadline) block.appendChild(makeText('p', 'bkbg-oh-sub', o.subheadline, { color: o.subColor })); |
| 79 |
} |
| 80 |
|
| 81 |
// List |
| 82 |
var listClass = 'bkbg-oh-list bkbg-oh-layout-' + o.layout + ' bkbg-oh-style-' + o.style; |
| 83 |
var list = makeEl('div', listClass, { gap: o.gap + 'px' }); |
| 84 |
|
| 85 |
o.objections.forEach(function (obj) { |
| 86 |
var pair = makeEl('div', 'bkbg-oh-pair', { borderRadius: o.borderRadius + 'px' }); |
| 87 |
|
| 88 |
var isCard = o.style === 'card'; |
| 89 |
var objRadius = isCard ? o.borderRadius + 'px' : o.borderRadius + 'px 0 0 ' + o.borderRadius + 'px'; |
| 90 |
var resRadius = isCard ? o.borderRadius + 'px' : '0 ' + o.borderRadius + 'px ' + o.borderRadius + 'px 0'; |
| 91 |
|
| 92 |
// Objection side |
| 93 |
var objSide = makeEl('div', 'bkbg-oh-objection', { |
| 94 |
background: o.objectionBg, |
| 95 |
color: o.objectionColor, |
| 96 |
borderColor: o.objectionBorderColor, |
| 97 |
borderRadius: objRadius |
| 98 |
}); |
| 99 |
|
| 100 |
var objHeader = makeEl('div', 'bkbg-oh-side-header'); |
| 101 |
if (o.showIcon) { |
| 102 |
var iconEl = makeEl('span', 'bkbg-oh-icon', { background: o.iconBg }); |
| 103 |
iconEl.textContent = obj.icon || '❓'; |
| 104 |
objHeader.appendChild(iconEl); |
| 105 |
} |
| 106 |
objHeader.appendChild(makeText('span', 'bkbg-oh-side-label', o.objectionLabel, { color: o.labelColor })); |
| 107 |
objSide.appendChild(objHeader); |
| 108 |
objSide.appendChild(makeText('p', 'bkbg-oh-objection-text', '"' + obj.objection + '"')); |
| 109 |
|
| 110 |
// Arrow (split style) |
| 111 |
if (o.style === 'split') { |
| 112 |
var arrow = makeEl('div', 'bkbg-oh-arrow', { color: o.responseBg }); |
| 113 |
arrow.textContent = '▶'; |
| 114 |
pair.appendChild(objSide); |
| 115 |
pair.appendChild(arrow); |
| 116 |
} else { |
| 117 |
pair.appendChild(objSide); |
| 118 |
} |
| 119 |
|
| 120 |
// Response side |
| 121 |
var resSide = makeEl('div', 'bkbg-oh-response', { |
| 122 |
background: o.responseBg, |
| 123 |
color: o.responseColor, |
| 124 |
borderColor: o.responseBorderColor, |
| 125 |
borderRadius: resRadius |
| 126 |
}); |
| 127 |
|
| 128 |
var resHeader = makeEl('div', 'bkbg-oh-side-header'); |
| 129 |
var check = makeEl('span', 'bkbg-oh-check', { background: o.responseColor }); |
| 130 |
check.textContent = '✓'; |
| 131 |
resHeader.appendChild(check); |
| 132 |
resHeader.appendChild(makeText('span', 'bkbg-oh-side-label', o.responseLabel, { color: o.labelColor })); |
| 133 |
resSide.appendChild(resHeader); |
| 134 |
resSide.appendChild(makeText('p', 'bkbg-oh-response-text', obj.response)); |
| 135 |
|
| 136 |
pair.appendChild(resSide); |
| 137 |
list.appendChild(pair); |
| 138 |
}); |
| 139 |
|
| 140 |
block.appendChild(list); |
| 141 |
|
| 142 |
appEl.parentNode.insertBefore(block, appEl); |
| 143 |
appEl.style.display = 'none'; |
| 144 |
}); |
| 145 |
} |
| 146 |
|
| 147 |
if (document.readyState !== 'loading') { init(); } |
| 148 |
else { document.addEventListener('DOMContentLoaded', init); } |
| 149 |
})(); |
| 150 |
|