| 1 |
(function () { |
| 2 |
var _typoKeys = { |
| 3 |
family:'font-family', weight:'font-weight', style:'font-style', |
| 4 |
decoration:'text-decoration', transform:'text-transform', |
| 5 |
sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m', |
| 6 |
lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m', |
| 7 |
letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m', |
| 8 |
wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m' |
| 9 |
}; |
| 10 |
function typoCssVarsForEl(el, obj, prefix) { |
| 11 |
if (!obj || typeof obj !== 'object') return; |
| 12 |
Object.keys(_typoKeys).forEach(function (k) { |
| 13 |
var v = obj[k]; |
| 14 |
if (v === undefined || v === '' || v === null) return; |
| 15 |
if (k === 'sizeDesktop' || k === 'sizeTablet' || k === 'sizeMobile') v = v + (obj.sizeUnit || 'px'); |
| 16 |
else if (k === 'lineHeightDesktop' || k === 'lineHeightTablet' || k === 'lineHeightMobile') v = v + (obj.lineHeightUnit || ''); |
| 17 |
else if (k === 'letterSpacingDesktop' || k === 'letterSpacingTablet' || k === 'letterSpacingMobile') v = v + (obj.letterSpacingUnit || 'px'); |
| 18 |
else if (k === 'wordSpacingDesktop' || k === 'wordSpacingTablet' || k === 'wordSpacingMobile') v = v + (obj.wordSpacingUnit || 'px'); |
| 19 |
el.style.setProperty(prefix + _typoKeys[k], String(v)); |
| 20 |
}); |
| 21 |
} |
| 22 |
|
| 23 |
function init() { |
| 24 |
document.querySelectorAll('.bkbg-s2c-app').forEach(function (appEl) { |
| 25 |
if (appEl.dataset.rendered) return; |
| 26 |
appEl.dataset.rendered = '1'; |
| 27 |
var opts; |
| 28 |
try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; } |
| 29 |
var o = Object.assign({ |
| 30 |
items: [], stickyPosition: 'right', splitRatio: '50-50', |
| 31 |
stickyOffset: 80, imageRadius: 16, showDivider: true, showProgressBar: true, |
| 32 |
iconSize: 36, gap: 80, paddingTop: 0, paddingBottom: 0, |
| 33 |
bgColor: '', panelBg: '#f8f8fc', eyebrowColor: '#6366f1', |
| 34 |
titleColor: '#111827', textColor: '#6b7280', iconBg: '#ede9fe', |
| 35 |
dividerColor: '#e5e7eb', accentColor: '#6366f1' |
| 36 |
}, opts); |
| 37 |
|
| 38 |
var items = o.items || []; |
| 39 |
if (!items.length) { appEl.style.display = 'none'; return; } |
| 40 |
|
| 41 |
var ratioMap = { '50-50': [50, 50], '45-55': [45, 55], '55-45': [55, 45], '40-60': [40, 60], '60-40': [60, 40] }; |
| 42 |
var ratio = ratioMap[o.splitRatio] || [50, 50]; |
| 43 |
var isStickRight = o.stickyPosition === 'right'; |
| 44 |
|
| 45 |
function mk(tag, cls, style) { |
| 46 |
var n = document.createElement(tag); |
| 47 |
if (cls) n.className = cls; |
| 48 |
if (style) Object.assign(n.style, style); |
| 49 |
return n; |
| 50 |
} |
| 51 |
|
| 52 |
/* Section */ |
| 53 |
var section = mk('div', 'bkbg-s2c-section', { |
| 54 |
background: o.bgColor || '', |
| 55 |
paddingTop: o.paddingTop + 'px', |
| 56 |
paddingBottom: o.paddingBottom + 'px' |
| 57 |
}); |
| 58 |
typoCssVarsForEl(section, o.eyebrowTypo, '--bks2c-eb-'); |
| 59 |
typoCssVarsForEl(section, o.titleTypo, '--bks2c-tt-'); |
| 60 |
typoCssVarsForEl(section, o.bodyTypo, '--bks2c-bd-'); |
| 61 |
section.style.setProperty('--bks2c-title-fw', o.titleFontWeight || '800'); |
| 62 |
section.style.setProperty('--bks2c-title-lh', String(o.titleLineHeight || 1.2)); |
| 63 |
section.style.setProperty('--bks2c-body-lh', String(o.bodyLineHeight || 1.7)); |
| 64 |
|
| 65 |
var shell = mk('div', 'bkbg-s2c-shell'); |
| 66 |
|
| 67 |
/* Sticky panel */ |
| 68 |
var stickyColW = (isStickRight ? ratio[1] : ratio[0]); |
| 69 |
var scrollColW = (isStickRight ? ratio[0] : ratio[1]); |
| 70 |
|
| 71 |
var stickyCol = mk('div', 'bkbg-s2c-sticky', { |
| 72 |
width: stickyColW + '%', |
| 73 |
top: o.stickyOffset + 'px' |
| 74 |
}); |
| 75 |
|
| 76 |
var panelImg = mk('div', 'bkbg-s2c-panel-img', { |
| 77 |
borderRadius: o.imageRadius + 'px', |
| 78 |
background: o.panelBg |
| 79 |
}); |
| 80 |
|
| 81 |
var firstItem = items[0] || {}; |
| 82 |
var stickyImg = null; |
| 83 |
var stickyPlaceholder = null; |
| 84 |
|
| 85 |
if (firstItem.imageUrl) { |
| 86 |
stickyImg = document.createElement('img'); |
| 87 |
stickyImg.src = firstItem.imageUrl; |
| 88 |
stickyImg.alt = firstItem.imageAlt || ''; |
| 89 |
panelImg.appendChild(stickyImg); |
| 90 |
} else { |
| 91 |
stickyPlaceholder = mk('div', 'bkbg-s2c-panel-placeholder', { |
| 92 |
background: ((firstItem.accentColor || o.accentColor) + '15'), |
| 93 |
minHeight: '280px' |
| 94 |
}); |
| 95 |
var _IP0 = window.bkbgIconPicker; |
| 96 |
var _t0 = firstItem.iconType || 'custom-char'; |
| 97 |
if (_IP0 && _t0 !== 'custom-char') { |
| 98 |
var _n0 = _IP0.buildFrontendIcon(_t0, firstItem.icon, firstItem.iconDashicon, firstItem.iconImageUrl, firstItem.iconDashiconColor); |
| 99 |
if (_n0) stickyPlaceholder.appendChild(_n0); else stickyPlaceholder.textContent = firstItem.icon || '🖼️'; |
| 100 |
} else { stickyPlaceholder.textContent = firstItem.icon || '🖼️'; } |
| 101 |
panelImg.appendChild(stickyPlaceholder); |
| 102 |
} |
| 103 |
|
| 104 |
stickyCol.appendChild(panelImg); |
| 105 |
|
| 106 |
/* Progress bar */ |
| 107 |
var progressBar = null; |
| 108 |
var progressFill = null; |
| 109 |
if (o.showProgressBar) { |
| 110 |
progressBar = mk('div', 'bkbg-s2c-progress', { marginTop: '16px' }); |
| 111 |
progressFill = mk('div', 'bkbg-s2c-progress-fill', { background: o.accentColor }); |
| 112 |
progressBar.appendChild(progressFill); |
| 113 |
stickyCol.appendChild(progressBar); |
| 114 |
} |
| 115 |
|
| 116 |
/* Scrolling items column */ |
| 117 |
var scrollCol = mk('div', 'bkbg-s2c-scroll', { |
| 118 |
width: scrollColW + '%', |
| 119 |
borderLeft: isStickRight && o.showDivider ? ('1px solid ' + o.dividerColor) : 'none', |
| 120 |
borderRight: !isStickRight && o.showDivider ? ('1px solid ' + o.dividerColor) : 'none', |
| 121 |
paddingLeft: isStickRight && o.showDivider ? '0' : '0' |
| 122 |
}); |
| 123 |
|
| 124 |
var itemEls = []; |
| 125 |
var activeIdx = 0; |
| 126 |
|
| 127 |
function updateSticky(idx) { |
| 128 |
activeIdx = idx; |
| 129 |
var it = items[idx]; |
| 130 |
var accent = it.accentColor || o.accentColor; |
| 131 |
|
| 132 |
/* update progress */ |
| 133 |
if (progressFill) { |
| 134 |
progressFill.style.width = ((idx + 1) / items.length * 100) + '%'; |
| 135 |
progressFill.style.background = accent; |
| 136 |
} |
| 137 |
|
| 138 |
/* update image */ |
| 139 |
if (it.imageUrl) { |
| 140 |
if (!stickyImg) { |
| 141 |
stickyImg = document.createElement('img'); |
| 142 |
stickyImg.style.cssText = 'width:100%;height:100%;object-fit:cover;display:block;transition:opacity 0.4s ease;border-radius:' + o.imageRadius + 'px'; |
| 143 |
if (stickyPlaceholder) { panelImg.replaceChild(stickyImg, stickyPlaceholder); stickyPlaceholder = null; } |
| 144 |
else { panelImg.appendChild(stickyImg); } |
| 145 |
} |
| 146 |
panelImg.classList.add('fading'); |
| 147 |
setTimeout(function () { |
| 148 |
stickyImg.src = it.imageUrl; |
| 149 |
stickyImg.alt = it.imageAlt || ''; |
| 150 |
panelImg.classList.remove('fading'); |
| 151 |
}, 200); |
| 152 |
} else { |
| 153 |
if (!stickyPlaceholder) { |
| 154 |
stickyPlaceholder = mk('div', 'bkbg-s2c-panel-placeholder', { minHeight: '280px' }); |
| 155 |
if (stickyImg) { panelImg.replaceChild(stickyPlaceholder, stickyImg); stickyImg = null; } |
| 156 |
else { panelImg.appendChild(stickyPlaceholder); } |
| 157 |
} |
| 158 |
var _IP2 = window.bkbgIconPicker; |
| 159 |
var _pType = it.iconType || 'custom-char'; |
| 160 |
if (_IP2 && _pType !== 'custom-char') { |
| 161 |
stickyPlaceholder.innerHTML = ''; |
| 162 |
var _pn = _IP2.buildFrontendIcon(_pType, it.icon, it.iconDashicon, it.iconImageUrl, it.iconDashiconColor); |
| 163 |
if (_pn) stickyPlaceholder.appendChild(_pn); else stickyPlaceholder.textContent = it.icon || '🖼️'; |
| 164 |
} else { stickyPlaceholder.textContent = it.icon || '🖼️'; } |
| 165 |
stickyPlaceholder.style.background = accent + '15'; |
| 166 |
} |
| 167 |
|
| 168 |
/* update items active state */ |
| 169 |
itemEls.forEach(function (info, i) { |
| 170 |
var isAct = i === idx; |
| 171 |
var iAccent = items[i].accentColor || o.accentColor; |
| 172 |
info.el.classList.toggle('active', isAct); |
| 173 |
if (isStickRight) { |
| 174 |
info.el.style.borderLeft = '3px solid ' + (isAct ? iAccent : 'transparent'); |
| 175 |
info.el.style.paddingLeft = '24px'; |
| 176 |
} else { |
| 177 |
info.el.style.borderRight = '3px solid ' + (isAct ? iAccent : 'transparent'); |
| 178 |
info.el.style.paddingRight = '24px'; |
| 179 |
} |
| 180 |
info.icon.style.background = isAct ? (iAccent + '20') : o.iconBg; |
| 181 |
info.eyebrow.style.color = isAct ? iAccent : o.textColor; |
| 182 |
}); |
| 183 |
} |
| 184 |
|
| 185 |
items.forEach(function (it, idx) { |
| 186 |
var accent = it.accentColor || o.accentColor; |
| 187 |
var wrapper = mk('div', 'bkbg-s2c-item' + (idx === 0 ? ' active' : ''), { |
| 188 |
paddingBottom: idx < items.length - 1 ? o.gap + 'px' : '28px', |
| 189 |
paddingTop: '28px', |
| 190 |
borderLeft: isStickRight ? ('3px solid ' + (idx === 0 ? accent : 'transparent')) : 'none', |
| 191 |
paddingLeft: isStickRight ? '24px' : '0', |
| 192 |
borderRight: !isStickRight ? ('3px solid ' + (idx === 0 ? accent : 'transparent')) : 'none', |
| 193 |
paddingRight: !isStickRight ? '24px' : '0' |
| 194 |
}); |
| 195 |
|
| 196 |
var inner = mk('div', 'bkbg-s2c-item-inner'); |
| 197 |
|
| 198 |
var iconEl = mk('div', 'bkbg-s2c-icon', { |
| 199 |
width: o.iconSize + 'px', |
| 200 |
height: o.iconSize + 'px', |
| 201 |
background: idx === 0 ? (accent + '20') : o.iconBg, |
| 202 |
fontSize: Math.round(o.iconSize * 0.55) + 'px' |
| 203 |
}); |
| 204 |
var _IP = window.bkbgIconPicker; |
| 205 |
var _iType = it.iconType || 'custom-char'; |
| 206 |
if (_IP && _iType !== 'custom-char') { |
| 207 |
var _in = _IP.buildFrontendIcon(_iType, it.icon, it.iconDashicon, it.iconImageUrl, it.iconDashiconColor); |
| 208 |
if (_in) iconEl.appendChild(_in); else iconEl.textContent = it.icon || '●'; |
| 209 |
} else { iconEl.textContent = it.icon || '●'; } |
| 210 |
inner.appendChild(iconEl); |
| 211 |
|
| 212 |
var textWrap = mk('div', 'bkbg-s2c-item-text'); |
| 213 |
var eyebrow = mk('div', 'bkbg-s2c-eyebrow', { color: idx === 0 ? accent : o.textColor }); |
| 214 |
eyebrow.textContent = it.eyebrow || ''; |
| 215 |
textWrap.appendChild(eyebrow); |
| 216 |
|
| 217 |
var titleEl = mk('h3', 'bkbg-s2c-title', { color: o.titleColor }); |
| 218 |
titleEl.innerHTML = it.title || ''; |
| 219 |
textWrap.appendChild(titleEl); |
| 220 |
|
| 221 |
var textEl = mk('p', 'bkbg-s2c-text', { color: o.textColor }); |
| 222 |
textEl.innerHTML = it.text || ''; |
| 223 |
textWrap.appendChild(textEl); |
| 224 |
|
| 225 |
inner.appendChild(textWrap); |
| 226 |
wrapper.appendChild(inner); |
| 227 |
scrollCol.appendChild(wrapper); |
| 228 |
itemEls.push({ el: wrapper, icon: iconEl, eyebrow: eyebrow }); |
| 229 |
}); |
| 230 |
|
| 231 |
/* IntersectionObserver */ |
| 232 |
var obs = new IntersectionObserver(function (entries) { |
| 233 |
entries.forEach(function (entry) { |
| 234 |
if (entry.isIntersecting) { |
| 235 |
var idx = itemEls.findIndex(function (info) { return info.el === entry.target; }); |
| 236 |
if (idx < 0) { |
| 237 |
/* IE-safe fallback */ |
| 238 |
for (var j = 0; j < itemEls.length; j++) { |
| 239 |
if (itemEls[j].el === entry.target) { idx = j; break; } |
| 240 |
} |
| 241 |
} |
| 242 |
if (idx >= 0) updateSticky(idx); |
| 243 |
} |
| 244 |
}); |
| 245 |
}, { threshold: 0.5 }); |
| 246 |
|
| 247 |
itemEls.forEach(function (info) { obs.observe(info.el); }); |
| 248 |
|
| 249 |
if (isStickRight) { |
| 250 |
shell.appendChild(scrollCol); |
| 251 |
shell.appendChild(stickyCol); |
| 252 |
} else { |
| 253 |
shell.appendChild(stickyCol); |
| 254 |
shell.appendChild(scrollCol); |
| 255 |
} |
| 256 |
|
| 257 |
section.appendChild(shell); |
| 258 |
updateSticky(0); |
| 259 |
appEl.parentNode.insertBefore(section, appEl); |
| 260 |
}); |
| 261 |
} |
| 262 |
|
| 263 |
if (document.readyState !== 'loading') { init(); } |
| 264 |
else { document.addEventListener('DOMContentLoaded', init); } |
| 265 |
})(); |
| 266 |
|