| 1 |
(function () { |
| 2 |
'use strict'; |
| 3 |
|
| 4 |
function typoCssVarsForEl(typo, prefix, el) { |
| 5 |
if (!typo || typeof typo !== 'object') return; |
| 6 |
var map = { |
| 7 |
family:'font-family', weight:'font-weight', style:'font-style', |
| 8 |
decoration:'text-decoration', transform:'text-transform', |
| 9 |
sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m', |
| 10 |
lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m', |
| 11 |
letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m', |
| 12 |
wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m' |
| 13 |
}; |
| 14 |
Object.keys(map).forEach(function(k) { |
| 15 |
if (typo[k] !== undefined && typo[k] !== '') { |
| 16 |
var v = typo[k]; |
| 17 |
if (['sizeDesktop','sizeTablet','sizeMobile'].indexOf(k) !== -1) v = v + (typo.sizeUnit || 'px'); |
| 18 |
else if (['lineHeightDesktop','lineHeightTablet','lineHeightMobile'].indexOf(k) !== -1) v = v + (typo.lineHeightUnit || ''); |
| 19 |
else if (['letterSpacingDesktop','letterSpacingTablet','letterSpacingMobile'].indexOf(k) !== -1) v = v + (typo.letterSpacingUnit || 'px'); |
| 20 |
else if (['wordSpacingDesktop','wordSpacingTablet','wordSpacingMobile'].indexOf(k) !== -1) v = v + (typo.wordSpacingUnit || 'px'); |
| 21 |
el.style.setProperty(prefix + map[k], String(v)); |
| 22 |
} |
| 23 |
}); |
| 24 |
} |
| 25 |
|
| 26 |
function init() { |
| 27 |
document.querySelectorAll('.bkbg-aser-app').forEach(function (appEl) { |
| 28 |
if (appEl.dataset.rendered) return; |
| 29 |
appEl.dataset.rendered = '1'; |
| 30 |
|
| 31 |
var opts; |
| 32 |
try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; } |
| 33 |
var o = Object.assign({ |
| 34 |
seriesTitle: 'Article Series', |
| 35 |
seriesDescription: '', |
| 36 |
currentPart: 1, |
| 37 |
parts: [], |
| 38 |
showProgress: true, |
| 39 |
showExcerpt: true, |
| 40 |
showNumbers: true, |
| 41 |
showSeriesDescription: true, |
| 42 |
layout: 'list', |
| 43 |
borderRadius: 12, |
| 44 |
bgColor: '#f8fafc', |
| 45 |
borderColor: '#e2e8f0', |
| 46 |
titleColor: '#0f172a', |
| 47 |
descColor: '#64748b', |
| 48 |
itemBg: '#ffffff', |
| 49 |
itemColor: '#334155', |
| 50 |
itemBorderColor: '#e2e8f0', |
| 51 |
excerptColor: '#94a3b8', |
| 52 |
currentBg: '#eff6ff', |
| 53 |
currentColor: '#1d4ed8', |
| 54 |
currentBorderColor: '#3b82f6', |
| 55 |
accentColor: '#3b82f6', |
| 56 |
progressBg: '#e2e8f0', |
| 57 |
progressColor: '#3b82f6', |
| 58 |
numberBg: '#e2e8f0', |
| 59 |
numberColor: '#64748b', |
| 60 |
currentNumberBg: '#3b82f6', |
| 61 |
currentNumberColor: '#ffffff' |
| 62 |
}, opts); |
| 63 |
|
| 64 |
var total = o.parts.length; |
| 65 |
var pct = total > 0 ? Math.round((o.currentPart / total) * 100) : 0; |
| 66 |
|
| 67 |
// ── build block ────────────────────────────────────────────────────── |
| 68 |
var block = document.createElement('div'); |
| 69 |
block.className = 'bkbg-aser-block'; |
| 70 |
block.style.background = o.bgColor; |
| 71 |
block.style.borderColor = o.borderColor; |
| 72 |
block.style.borderRadius = o.borderRadius + 'px'; |
| 73 |
block.style.setProperty('--bkbg-aser-title-sz', (o.titleFontSize || 20) + 'px'); |
| 74 |
block.style.setProperty('--bkbg-aser-desc-sz', (o.descFontSize || 14) + 'px'); |
| 75 |
block.style.setProperty('--bkbg-aser-pt-sz', (o.partTitleFontSize || 14) + 'px'); |
| 76 |
block.style.setProperty('--bkbg-aser-exc-sz', (o.excerptFontSize || 12) + 'px'); |
| 77 |
typoCssVarsForEl(o.titleTypo, '--bkbg-aser-title-', block); |
| 78 |
typoCssVarsForEl(o.descTypo, '--bkbg-aser-desc-', block); |
| 79 |
typoCssVarsForEl(o.partTitleTypo, '--bkbg-aser-pt-', block); |
| 80 |
typoCssVarsForEl(o.excerptTypo, '--bkbg-aser-exc-', block); |
| 81 |
|
| 82 |
// Header |
| 83 |
var header = document.createElement('div'); |
| 84 |
header.className = 'bkbg-aser-header'; |
| 85 |
|
| 86 |
var label = document.createElement('div'); |
| 87 |
label.className = 'bkbg-aser-series-label'; |
| 88 |
label.textContent = 'Article Series'; |
| 89 |
label.style.color = o.accentColor; |
| 90 |
header.appendChild(label); |
| 91 |
|
| 92 |
var titleEl = document.createElement('h3'); |
| 93 |
titleEl.className = 'bkbg-aser-title'; |
| 94 |
titleEl.textContent = o.seriesTitle; |
| 95 |
titleEl.style.color = o.titleColor; |
| 96 |
header.appendChild(titleEl); |
| 97 |
|
| 98 |
if (o.showSeriesDescription && o.seriesDescription) { |
| 99 |
var descEl = document.createElement('p'); |
| 100 |
descEl.className = 'bkbg-aser-desc'; |
| 101 |
descEl.textContent = o.seriesDescription; |
| 102 |
descEl.style.color = o.descColor; |
| 103 |
header.appendChild(descEl); |
| 104 |
} |
| 105 |
block.appendChild(header); |
| 106 |
|
| 107 |
// Progress |
| 108 |
if (o.showProgress && total > 0) { |
| 109 |
var progressWrap = document.createElement('div'); |
| 110 |
progressWrap.className = 'bkbg-aser-progress-wrap'; |
| 111 |
|
| 112 |
var bar = document.createElement('div'); |
| 113 |
bar.className = 'bkbg-aser-progress-bar'; |
| 114 |
bar.style.background = o.progressBg; |
| 115 |
|
| 116 |
var fill = document.createElement('div'); |
| 117 |
fill.className = 'bkbg-aser-progress-fill'; |
| 118 |
fill.style.background = o.progressColor; |
| 119 |
fill.style.width = pct + '%'; |
| 120 |
bar.appendChild(fill); |
| 121 |
|
| 122 |
var progLabel = document.createElement('span'); |
| 123 |
progLabel.className = 'bkbg-aser-progress-label'; |
| 124 |
progLabel.textContent = 'Part ' + o.currentPart + ' of ' + total; |
| 125 |
progLabel.style.color = o.descColor; |
| 126 |
|
| 127 |
progressWrap.appendChild(bar); |
| 128 |
progressWrap.appendChild(progLabel); |
| 129 |
block.appendChild(progressWrap); |
| 130 |
} |
| 131 |
|
| 132 |
// Parts list |
| 133 |
var list = document.createElement('ol'); |
| 134 |
list.className = 'bkbg-aser-list bkbg-aser-layout-' + o.layout; |
| 135 |
list.style.listStyle = 'none'; |
| 136 |
list.style.margin = '0'; |
| 137 |
list.style.padding = '0'; |
| 138 |
|
| 139 |
o.parts.forEach(function (part, i) { |
| 140 |
var isCurrent = i + 1 === o.currentPart; |
| 141 |
|
| 142 |
var li = document.createElement('li'); |
| 143 |
li.className = 'bkbg-aser-item' + (isCurrent ? ' is-current' : ''); |
| 144 |
|
| 145 |
if (!isCurrent && part.url && part.url !== '#') { |
| 146 |
// Make non-current items clickable (wrap inner content in link) |
| 147 |
li.style.cursor = 'pointer'; |
| 148 |
li.addEventListener('click', function () { window.location.href = part.url; }); |
| 149 |
} |
| 150 |
|
| 151 |
li.style.background = isCurrent ? o.currentBg : o.itemBg; |
| 152 |
li.style.color = isCurrent ? o.currentColor : o.itemColor; |
| 153 |
li.style.borderColor = isCurrent ? o.currentBorderColor : o.itemBorderColor; |
| 154 |
li.style.borderRadius = Math.max(0, o.borderRadius - 4) + 'px'; |
| 155 |
if (isCurrent) { |
| 156 |
li.style.borderLeftWidth = '3px'; |
| 157 |
li.style.paddingLeft = '12px'; |
| 158 |
} |
| 159 |
|
| 160 |
if (o.showNumbers) { |
| 161 |
var num = document.createElement('span'); |
| 162 |
num.className = 'bkbg-aser-num'; |
| 163 |
num.textContent = String(i + 1); |
| 164 |
num.style.background = isCurrent ? o.currentNumberBg : o.numberBg; |
| 165 |
num.style.color = isCurrent ? o.currentNumberColor : o.numberColor; |
| 166 |
li.appendChild(num); |
| 167 |
} |
| 168 |
|
| 169 |
var body = document.createElement('div'); |
| 170 |
body.className = 'bkbg-aser-item-body'; |
| 171 |
|
| 172 |
var partTitle = document.createElement('span'); |
| 173 |
partTitle.className = 'bkbg-aser-part-title'; |
| 174 |
partTitle.textContent = part.title; |
| 175 |
partTitle.style.color = isCurrent ? o.currentColor : o.itemColor; |
| 176 |
body.appendChild(partTitle); |
| 177 |
|
| 178 |
if (o.showExcerpt && part.excerpt) { |
| 179 |
var excerpt = document.createElement('span'); |
| 180 |
excerpt.className = 'bkbg-aser-excerpt'; |
| 181 |
excerpt.textContent = part.excerpt; |
| 182 |
excerpt.style.color = isCurrent ? o.currentColor : o.excerptColor; |
| 183 |
body.appendChild(excerpt); |
| 184 |
} |
| 185 |
|
| 186 |
li.appendChild(body); |
| 187 |
|
| 188 |
if (isCurrent) { |
| 189 |
var badge = document.createElement('span'); |
| 190 |
badge.className = 'bkbg-aser-current-badge'; |
| 191 |
badge.textContent = 'Current'; |
| 192 |
badge.style.background = o.accentColor; |
| 193 |
li.appendChild(badge); |
| 194 |
} |
| 195 |
|
| 196 |
list.appendChild(li); |
| 197 |
}); |
| 198 |
|
| 199 |
block.appendChild(list); |
| 200 |
|
| 201 |
appEl.parentNode.insertBefore(block, appEl); |
| 202 |
appEl.style.display = 'none'; |
| 203 |
}); |
| 204 |
} |
| 205 |
|
| 206 |
if (document.readyState !== 'loading') { init(); } |
| 207 |
else { document.addEventListener('DOMContentLoaded', init); } |
| 208 |
})(); |
| 209 |
|