| 1 |
(function () { |
| 2 |
function init() { |
| 3 |
document.querySelectorAll('.bkbg-ts-app').forEach(function (appEl) { |
| 4 |
if (appEl.dataset.rendered) return; |
| 5 |
appEl.dataset.rendered = '1'; |
| 6 |
var opts; |
| 7 |
try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; } |
| 8 |
var o = Object.assign({ |
| 9 |
heading: '', showHeading: false, |
| 10 |
members: [], perView: 3, |
| 11 |
autoplay: false, autoplayDelay: 4000, |
| 12 |
showArrows: true, showDots: true, |
| 13 |
showBio: true, showSocials: true, showTag: true, |
| 14 |
cardStyle: 'default', avatarSize: 80, avatarRadius: 50, cardRadius: 12, |
| 15 |
paddingTop: 0, paddingBottom: 0, |
| 16 |
bgColor: '', cardBg: '#ffffff', cardBorder: '#e5e7eb', |
| 17 |
nameColor: '#111827', roleColor: '#6366f1', bioColor: '#6b7280', |
| 18 |
tagBg: '#ede9fe', tagColor: '#6366f1', socialColor: '#6b7280', |
| 19 |
dotColor: '#d1d5db', dotActive: '#6366f1', |
| 20 |
arrowBg: '#ffffff', arrowColor: '#374151', accentColor: '#6366f1' |
| 21 |
}, opts); |
| 22 |
|
| 23 |
var members = o.members || []; |
| 24 |
if (!members.length) { appEl.style.display = 'none'; return; } |
| 25 |
|
| 26 |
function mk(tag, cls, style, text) { |
| 27 |
var n = document.createElement(tag); |
| 28 |
if (cls) n.className = cls; |
| 29 |
if (style) Object.assign(n.style, style); |
| 30 |
if (text != null) n.textContent = text; |
| 31 |
return n; |
| 32 |
} |
| 33 |
|
| 34 |
var section = mk('div', 'bkbg-ts-section', { |
| 35 |
background: o.bgColor || undefined, |
| 36 |
paddingTop: o.paddingTop + 'px', |
| 37 |
paddingBottom: o.paddingBottom + 'px' |
| 38 |
}); |
| 39 |
|
| 40 |
if (o.showHeading && o.heading) { |
| 41 |
section.appendChild(mk('h2', 'bkbg-ts-heading', { color: o.nameColor }, o.heading)); |
| 42 |
} |
| 43 |
|
| 44 |
/* responsive perView */ |
| 45 |
var perView = parseInt(o.perView, 10) || 3; |
| 46 |
|
| 47 |
var viewport = mk('div', 'bkbg-ts-viewport'); |
| 48 |
var track = mk('div', 'bkbg-ts-track'); |
| 49 |
|
| 50 |
members.forEach(function (m) { |
| 51 |
var slide = mk('div', 'bkbg-ts-slide'); |
| 52 |
slide.style.width = (100 / perView) + '%'; |
| 53 |
|
| 54 |
var isCentered = o.cardStyle === 'centered'; |
| 55 |
var isHorizontal = o.cardStyle === 'horizontal'; |
| 56 |
|
| 57 |
var card = mk('div', 'bkbg-ts-card bkbg-ts-' + o.cardStyle, { |
| 58 |
background: o.cardBg, |
| 59 |
borderColor: o.cardBorder, |
| 60 |
borderRadius: o.cardRadius + 'px' |
| 61 |
}); |
| 62 |
|
| 63 |
var body = mk('div', 'bkbg-ts-card-body'); |
| 64 |
|
| 65 |
/* avatar */ |
| 66 |
var avatarWrap = mk('div', 'bkbg-ts-avatar-wrap', { |
| 67 |
width: o.avatarSize + 'px', |
| 68 |
height: o.avatarSize + 'px', |
| 69 |
borderRadius: o.avatarRadius + '%' |
| 70 |
}); |
| 71 |
if (m.imageUrl) { |
| 72 |
var img = document.createElement('img'); |
| 73 |
img.src = m.imageUrl; |
| 74 |
img.alt = m.imageAlt || m.name || ''; |
| 75 |
avatarWrap.appendChild(img); |
| 76 |
} else { |
| 77 |
avatarWrap.textContent = '👤'; |
| 78 |
} |
| 79 |
|
| 80 |
var textWrap = mk('div', 'bkbg-ts-text', { flex: 1 }); |
| 81 |
|
| 82 |
if (o.showTag && m.tag) { |
| 83 |
textWrap.appendChild(mk('span', 'bkbg-ts-tag', { background: o.tagBg, color: o.tagColor }, m.tag)); |
| 84 |
} |
| 85 |
|
| 86 |
var nameEl = mk('h3', 'bkbg-ts-name', { color: o.nameColor }, m.name || ''); |
| 87 |
textWrap.appendChild(nameEl); |
| 88 |
|
| 89 |
if (m.role) { |
| 90 |
textWrap.appendChild(mk('p', 'bkbg-ts-role', { color: o.roleColor }, m.role)); |
| 91 |
} |
| 92 |
|
| 93 |
if (o.showBio && m.bio) { |
| 94 |
var bio = mk('p', 'bkbg-ts-bio', { color: o.bioColor }, ''); |
| 95 |
bio.innerHTML = m.bio; |
| 96 |
textWrap.appendChild(bio); |
| 97 |
} |
| 98 |
|
| 99 |
if (o.showSocials && (m.linkedin || m.twitter || m.email || m.website)) { |
| 100 |
var socials = mk('div', 'bkbg-ts-socials'); |
| 101 |
var addSocial = function (url, icon, label) { |
| 102 |
if (!url) return; |
| 103 |
var link = mk('a', 'bkbg-ts-social', { color: o.socialColor, border: '1px solid ' + o.cardBorder }, icon); |
| 104 |
link.href = url.indexOf('@') > -1 ? 'mailto:' + url : url; |
| 105 |
link.target = '_blank'; |
| 106 |
link.rel = 'noopener noreferrer'; |
| 107 |
link.title = label; |
| 108 |
socials.appendChild(link); |
| 109 |
}; |
| 110 |
addSocial(m.linkedin, 'in', 'LinkedIn'); |
| 111 |
addSocial(m.twitter, '𝕏', 'Twitter/X'); |
| 112 |
addSocial(m.email, '✉', 'Email'); |
| 113 |
addSocial(m.website, '🌐', 'Website'); |
| 114 |
textWrap.appendChild(socials); |
| 115 |
} |
| 116 |
|
| 117 |
if (isHorizontal) { |
| 118 |
body.appendChild(avatarWrap); |
| 119 |
body.appendChild(textWrap); |
| 120 |
} else { |
| 121 |
body.appendChild(avatarWrap); |
| 122 |
body.appendChild(textWrap); |
| 123 |
} |
| 124 |
card.appendChild(body); |
| 125 |
slide.appendChild(card); |
| 126 |
track.appendChild(slide); |
| 127 |
}); |
| 128 |
|
| 129 |
viewport.appendChild(track); |
| 130 |
section.appendChild(viewport); |
| 131 |
|
| 132 |
/* navigation */ |
| 133 |
var current = 0; |
| 134 |
var maxSlide = Math.max(0, members.length - perView); |
| 135 |
|
| 136 |
var nav = mk('div', 'bkbg-ts-nav'); |
| 137 |
var prevBtn, nextBtn, dots; |
| 138 |
|
| 139 |
function goTo(idx) { |
| 140 |
current = Math.max(0, Math.min(idx, maxSlide)); |
| 141 |
track.style.transform = 'translateX(-' + (current * (100 / perView)) + '%)'; |
| 142 |
if (prevBtn) { prevBtn.classList.toggle('disabled', current === 0); } |
| 143 |
if (nextBtn) { nextBtn.classList.toggle('disabled', current >= maxSlide); } |
| 144 |
if (dots) { |
| 145 |
dots.querySelectorAll('.bkbg-ts-dot').forEach(function (d, i) { |
| 146 |
d.classList.toggle('active', i === current); |
| 147 |
d.style.background = i === current ? o.dotActive : o.dotColor; |
| 148 |
d.style.width = i === current ? '22px' : '8px'; |
| 149 |
}); |
| 150 |
} |
| 151 |
} |
| 152 |
|
| 153 |
if (o.showArrows) { |
| 154 |
prevBtn = mk('div', 'bkbg-ts-arrow', { background: o.arrowBg, color: o.arrowColor, borderColor: o.cardBorder }, '←'); |
| 155 |
prevBtn.addEventListener('click', function () { goTo(current - 1); }); |
| 156 |
nav.appendChild(prevBtn); |
| 157 |
} |
| 158 |
|
| 159 |
if (o.showDots) { |
| 160 |
dots = mk('div', 'bkbg-ts-dots'); |
| 161 |
members.forEach(function (_, i) { |
| 162 |
var d = mk('div', 'bkbg-ts-dot' + (i === 0 ? ' active' : ''), { background: i === 0 ? o.dotActive : o.dotColor }); |
| 163 |
if (i === 0) { d.style.width = '22px'; } |
| 164 |
d.addEventListener('click', function () { goTo(i); }); |
| 165 |
dots.appendChild(d); |
| 166 |
}); |
| 167 |
nav.appendChild(dots); |
| 168 |
} |
| 169 |
|
| 170 |
if (o.showArrows) { |
| 171 |
nextBtn = mk('div', 'bkbg-ts-arrow', { background: o.arrowBg, color: o.arrowColor, borderColor: o.cardBorder }, '→'); |
| 172 |
nextBtn.addEventListener('click', function () { goTo(current + 1); }); |
| 173 |
nav.appendChild(nextBtn); |
| 174 |
} |
| 175 |
|
| 176 |
goTo(0); |
| 177 |
section.appendChild(nav); |
| 178 |
|
| 179 |
/* autoplay */ |
| 180 |
if (o.autoplay) { |
| 181 |
setInterval(function () { |
| 182 |
goTo(current >= maxSlide ? 0 : current + 1); |
| 183 |
}, o.autoplayDelay || 4000); |
| 184 |
} |
| 185 |
|
| 186 |
/* responsive: reduce perView on small screens */ |
| 187 |
function handleResize() { |
| 188 |
var w = viewport.offsetWidth; |
| 189 |
var rPV = perView; |
| 190 |
if (w < 480) rPV = 1; |
| 191 |
else if (w < 768) rPV = Math.min(2, perView); |
| 192 |
track.querySelectorAll('.bkbg-ts-slide').forEach(function (s) { s.style.width = (100 / rPV) + '%'; }); |
| 193 |
} |
| 194 |
window.addEventListener('resize', handleResize); |
| 195 |
handleResize(); |
| 196 |
|
| 197 |
appEl.parentNode.insertBefore(section, appEl); |
| 198 |
}); |
| 199 |
} |
| 200 |
|
| 201 |
if (document.readyState !== 'loading') { init(); } |
| 202 |
else { document.addEventListener('DOMContentLoaded', init); } |
| 203 |
})(); |
| 204 |
|