| 1 |
(function () { |
| 2 |
'use strict'; |
| 3 |
|
| 4 |
/* ── typography CSS-var helper ──────────────────────── */ |
| 5 |
var _typoKeys = { |
| 6 |
family:'font-family', weight:'font-weight', style:'font-style', |
| 7 |
decoration:'text-decoration', transform:'text-transform', |
| 8 |
sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m', |
| 9 |
lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m', |
| 10 |
letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m', |
| 11 |
wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m' |
| 12 |
}; |
| 13 |
function typoCssVarsForEl(el, obj, prefix) { |
| 14 |
if (!obj || typeof obj !== 'object') return; |
| 15 |
Object.keys(_typoKeys).forEach(function (k) { |
| 16 |
var v = obj[k]; |
| 17 |
if (v === undefined || v === '' || v === null) return; |
| 18 |
if (k === 'sizeDesktop' || k === 'sizeTablet' || k === 'sizeMobile') v = v + (obj.sizeUnit || 'px'); |
| 19 |
else if (k === 'lineHeightDesktop' || k === 'lineHeightTablet' || k === 'lineHeightMobile') v = v + (obj.lineHeightUnit || ''); |
| 20 |
else if (k === 'letterSpacingDesktop' || k === 'letterSpacingTablet' || k === 'letterSpacingMobile') v = v + (obj.letterSpacingUnit || 'px'); |
| 21 |
else if (k === 'wordSpacingDesktop' || k === 'wordSpacingTablet' || k === 'wordSpacingMobile') v = v + (obj.wordSpacingUnit || 'px'); |
| 22 |
el.style.setProperty(prefix + _typoKeys[k], String(v)); |
| 23 |
}); |
| 24 |
} |
| 25 |
|
| 26 |
document.querySelectorAll('.bkbg-job-app').forEach(function (root) { |
| 27 |
var a; |
| 28 |
try { a = JSON.parse(root.dataset.opts || '{}'); } catch (e) { return; } |
| 29 |
|
| 30 |
var bg = a.bgColor || '#ffffff'; |
| 31 |
var ptop = a.paddingTop !== undefined ? a.paddingTop : 80; |
| 32 |
var pbot = a.paddingBottom !== undefined ? a.paddingBottom : 80; |
| 33 |
var maxW = a.maxWidth || 1000; |
| 34 |
var jobs = a.jobs || []; |
| 35 |
var filterBy = a.filterBy || 'department'; |
| 36 |
var isGrid = a.layout === 'grid'; |
| 37 |
|
| 38 |
root.style.backgroundColor = bg; |
| 39 |
root.style.paddingTop = ptop + 'px'; |
| 40 |
root.style.paddingBottom = pbot + 'px'; |
| 41 |
|
| 42 |
typoCssVarsForEl(root, a.headingTypo, '--bkbg-jo-h-'); |
| 43 |
typoCssVarsForEl(root, a.eyebrowTypo, '--bkbg-jo-ew-'); |
| 44 |
typoCssVarsForEl(root, a.subtextTypo, '--bkbg-jo-st-'); |
| 45 |
typoCssVarsForEl(root, a.jobTitleTypo, '--bkbg-jo-jt-'); |
| 46 |
typoCssVarsForEl(root, a.jobDescTypo, '--bkbg-jo-jd-'); |
| 47 |
|
| 48 |
var inner = document.createElement('div'); |
| 49 |
inner.className = 'bkbg-job-inner'; |
| 50 |
inner.style.maxWidth = maxW + 'px'; |
| 51 |
|
| 52 |
// === Header === |
| 53 |
var header = document.createElement('div'); |
| 54 |
header.style.cssText = 'text-align:center;margin-bottom:48px;'; |
| 55 |
|
| 56 |
if (a.showEyebrow !== false && a.eyebrow) { |
| 57 |
var eyebrow = document.createElement('span'); |
| 58 |
eyebrow.className = 'bkbg-job-eyebrow'; |
| 59 |
eyebrow.style.cssText = 'display:inline-block;background:' + (a.eyebrowBg || '#f3f0ff') + ';color:' + (a.eyebrowColor || '#7c3aed') + ';padding:5px 14px;border-radius:999px;margin-bottom:16px;'; |
| 60 |
eyebrow.textContent = a.eyebrow; |
| 61 |
header.appendChild(eyebrow); |
| 62 |
} |
| 63 |
|
| 64 |
var heading = document.createElement('h2'); |
| 65 |
heading.className = 'bkbg-job-heading'; |
| 66 |
heading.style.cssText = 'color:' + (a.headingColor || '#111827') + ';margin:0 0 16px;'; |
| 67 |
heading.innerHTML = a.heading || ''; |
| 68 |
header.appendChild(heading); |
| 69 |
|
| 70 |
if (a.showSubtext !== false && a.subtext) { |
| 71 |
var sub = document.createElement('p'); |
| 72 |
sub.className = 'bkbg-job-subtext'; |
| 73 |
sub.style.cssText = 'color:' + (a.subtextColor || '#6b7280') + ';margin:0 auto;max-width:600px;'; |
| 74 |
sub.innerHTML = a.subtext; |
| 75 |
header.appendChild(sub); |
| 76 |
} |
| 77 |
|
| 78 |
inner.appendChild(header); |
| 79 |
|
| 80 |
// === Filter tabs === |
| 81 |
var activeFilter = 'all'; |
| 82 |
var filterValues = []; |
| 83 |
|
| 84 |
if (a.showFilter !== false) { |
| 85 |
var filtersEl = document.createElement('div'); |
| 86 |
filtersEl.className = 'bkbg-job-filters'; |
| 87 |
|
| 88 |
// Gather unique values |
| 89 |
filterValues = Array.from(new Set(jobs.map(function (j) { return j[filterBy]; }))).filter(Boolean); |
| 90 |
|
| 91 |
function setFilter(val) { |
| 92 |
activeFilter = val; |
| 93 |
// Update button states |
| 94 |
filtersEl.querySelectorAll('.bkbg-job-filter-btn').forEach(function (btn) { |
| 95 |
var isActive = btn.dataset.filter === val; |
| 96 |
btn.style.background = isActive ? (a.filterActiveBg || '#7c3aed') : (a.filterBg || '#f3f4f6'); |
| 97 |
btn.style.color = isActive ? (a.filterActiveColor || '#ffffff') : (a.filterColor || '#374151'); |
| 98 |
}); |
| 99 |
// Show/hide cards |
| 100 |
document.querySelectorAll('[data-job-idx]').forEach(function (card) { |
| 101 |
var idx = parseInt(card.dataset.jobIdx, 10); |
| 102 |
var job = jobs[idx]; |
| 103 |
var visible = val === 'all' || job[filterBy] === val; |
| 104 |
card.classList.toggle('bkbg-job-card--hidden', !visible); |
| 105 |
}); |
| 106 |
// Empty state |
| 107 |
var anyVisible = jobs.some(function (j) { |
| 108 |
return val === 'all' || j[filterBy] === val; |
| 109 |
}); |
| 110 |
if (noneEl) { |
| 111 |
noneEl.classList.toggle('bkbg-job-none--visible', !anyVisible); |
| 112 |
} |
| 113 |
} |
| 114 |
|
| 115 |
// All button |
| 116 |
var allBtn = document.createElement('button'); |
| 117 |
allBtn.className = 'bkbg-job-filter-btn'; |
| 118 |
allBtn.dataset.filter = 'all'; |
| 119 |
allBtn.textContent = 'All'; |
| 120 |
allBtn.style.cssText = 'background:' + (a.filterActiveBg || '#7c3aed') + ';color:' + (a.filterActiveColor || '#ffffff') + ';'; |
| 121 |
allBtn.addEventListener('click', function () { setFilter('all'); }); |
| 122 |
filtersEl.appendChild(allBtn); |
| 123 |
|
| 124 |
filterValues.forEach(function (val) { |
| 125 |
var btn = document.createElement('button'); |
| 126 |
btn.className = 'bkbg-job-filter-btn'; |
| 127 |
btn.dataset.filter = val; |
| 128 |
btn.textContent = val; |
| 129 |
btn.style.cssText = 'background:' + (a.filterBg || '#f3f4f6') + ';color:' + (a.filterColor || '#374151') + ';'; |
| 130 |
btn.addEventListener('click', function () { setFilter(val); }); |
| 131 |
filtersEl.appendChild(btn); |
| 132 |
}); |
| 133 |
|
| 134 |
inner.appendChild(filtersEl); |
| 135 |
} |
| 136 |
|
| 137 |
// === Job listings === |
| 138 |
var listings = document.createElement('div'); |
| 139 |
listings.className = isGrid ? 'bkbg-job-grid' : 'bkbg-job-list'; |
| 140 |
|
| 141 |
jobs.forEach(function (j, idx) { |
| 142 |
var card = document.createElement('div'); |
| 143 |
card.className = 'bkbg-job-card'; |
| 144 |
card.dataset.jobIdx = idx; |
| 145 |
card.style.cssText = 'background:' + (a.jobCardBg || '#f9fafb') + ';border-color:' + (a.jobCardBorder || '#e5e7eb') + ';'; |
| 146 |
|
| 147 |
// Tags |
| 148 |
var tags = document.createElement('div'); |
| 149 |
tags.className = 'bkbg-job-tags'; |
| 150 |
|
| 151 |
var deptTag = document.createElement('span'); |
| 152 |
deptTag.className = 'bkbg-job-tag'; |
| 153 |
deptTag.style.cssText = 'background:' + (a.deptBg || '#f3f0ff') + ';color:' + (a.deptColor || '#7c3aed') + ';'; |
| 154 |
deptTag.textContent = j.department; |
| 155 |
tags.appendChild(deptTag); |
| 156 |
|
| 157 |
var typeTag = document.createElement('span'); |
| 158 |
typeTag.className = 'bkbg-job-tag'; |
| 159 |
typeTag.style.cssText = 'background:' + (a.typeBg || '#f0fdf4') + ';color:' + (a.typeColor || '#15803d') + ';'; |
| 160 |
typeTag.textContent = j.type; |
| 161 |
tags.appendChild(typeTag); |
| 162 |
|
| 163 |
if (j.location) { |
| 164 |
var loc = document.createElement('span'); |
| 165 |
loc.className = 'bkbg-job-location'; |
| 166 |
loc.style.color = a.locationColor || '#6b7280'; |
| 167 |
loc.textContent = '📍 ' + j.location; |
| 168 |
tags.appendChild(loc); |
| 169 |
} |
| 170 |
|
| 171 |
card.appendChild(tags); |
| 172 |
|
| 173 |
// Title |
| 174 |
var titleEl = document.createElement('h3'); |
| 175 |
titleEl.className = 'bkbg-job-title'; |
| 176 |
titleEl.style.color = a.jobTitleColor || '#111827'; |
| 177 |
titleEl.innerHTML = j.title; |
| 178 |
card.appendChild(titleEl); |
| 179 |
|
| 180 |
// Description |
| 181 |
if (a.showDescription !== false && j.description) { |
| 182 |
var desc = document.createElement('p'); |
| 183 |
desc.className = 'bkbg-job-desc'; |
| 184 |
desc.style.color = a.jobDescColor || '#6b7280'; |
| 185 |
desc.innerHTML = j.description; |
| 186 |
card.appendChild(desc); |
| 187 |
} |
| 188 |
|
| 189 |
// Apply button |
| 190 |
var applyBtn = document.createElement('a'); |
| 191 |
applyBtn.className = 'bkbg-job-apply'; |
| 192 |
applyBtn.href = j.url || '#'; |
| 193 |
applyBtn.textContent = a.applyLabel || 'Apply Now →'; |
| 194 |
applyBtn.style.cssText = 'background:' + (a.applyBg || '#7c3aed') + ';color:' + (a.applyColor || '#ffffff') + ';'; |
| 195 |
if (a.openInNewTab) { |
| 196 |
applyBtn.target = '_blank'; |
| 197 |
applyBtn.rel = 'noopener noreferrer'; |
| 198 |
} |
| 199 |
card.appendChild(applyBtn); |
| 200 |
|
| 201 |
listings.appendChild(card); |
| 202 |
}); |
| 203 |
|
| 204 |
inner.appendChild(listings); |
| 205 |
|
| 206 |
// === Empty state === |
| 207 |
var noneEl = null; |
| 208 |
if (a.showNone !== false) { |
| 209 |
noneEl = document.createElement('div'); |
| 210 |
noneEl.className = 'bkbg-job-none'; |
| 211 |
noneEl.style.color = a.subtextColor || '#6b7280'; |
| 212 |
noneEl.textContent = a.noneText || 'No openings right now. Check back soon!'; |
| 213 |
inner.appendChild(noneEl); |
| 214 |
} |
| 215 |
|
| 216 |
root.appendChild(inner); |
| 217 |
}); |
| 218 |
})(); |
| 219 |
|